blob: 4dbcc9581a841342087065d7a984d67056e638ea [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"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000019#include "llvm/ADT/STLExtras.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
Tim Northover3b0846e2014-05-24 12:50:23 +000062class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000063private:
64 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000065
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000066 // Map of register aliases registers via the .req directive.
Eugene Zelenko049b0172017-01-06 00:30:53 +000067 StringMap<std::pair<bool, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000068
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000069 AArch64TargetStreamer &getTargetStreamer() {
70 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
71 return static_cast<AArch64TargetStreamer &>(TS);
72 }
73
Rafael Espindola961d4692014-11-11 05:18:41 +000074 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000075
76 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000077 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000078 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
79 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000080 unsigned matchRegisterNameAlias(StringRef Name, bool isVector);
Tim Northover3b0846e2014-05-24 12:50:23 +000081 int tryParseRegister();
82 int tryMatchVectorRegister(StringRef &Kind, bool expected);
83 bool parseRegister(OperandVector &Operands);
84 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
85 bool parseVectorList(OperandVector &Operands);
86 bool parseOperand(OperandVector &Operands, bool isCondCode,
87 bool invertCondCode);
88
Tim Northover3b0846e2014-05-24 12:50:23 +000089 bool showMatchError(SMLoc Loc, unsigned ErrCode);
90
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000091 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000092 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000093 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000094 bool parseDirectiveInst(SMLoc L);
95
Tim Northover3b0846e2014-05-24 12:50:23 +000096 bool parseDirectiveTLSDescCall(SMLoc L);
97
98 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000099 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000100
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000101 bool parseDirectiveReq(StringRef Name, SMLoc L);
102 bool parseDirectiveUnreq(SMLoc L);
103
Tim Northover3b0846e2014-05-24 12:50:23 +0000104 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
105 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
106 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000107 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000108 bool MatchingInlineAsm) override;
109/// @name Auto-generated Match Functions
110/// {
111
112#define GET_ASSEMBLER_HEADER
113#include "AArch64GenAsmMatcher.inc"
114
115 /// }
116
117 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
118 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
119 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
120 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
121 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
122 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000123 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000124 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
125 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
126 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
127 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
128 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
129 bool tryParseVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000130 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000131
132public:
133 enum AArch64MatchResultTy {
134 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
135#define GET_OPERAND_DIAGNOSTIC_TYPES
136#include "AArch64GenAsmMatcher.inc"
137 };
Joel Jones504bf332016-10-24 13:37:13 +0000138 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000139
Akira Hatanakab11ef082015-11-14 06:35:56 +0000140 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000141 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000142 : MCTargetAsmParser(Options, STI) {
Joel Jones504bf332016-10-24 13:37:13 +0000143 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000144 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000145 MCStreamer &S = getParser().getStreamer();
146 if (S.getTargetStreamer() == nullptr)
147 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000148
149 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000150 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000151 }
152
153 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
154 SMLoc NameLoc, OperandVector &Operands) override;
155 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
156 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000157 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000158 unsigned Kind) override;
159
160 static bool classifySymbolRef(const MCExpr *Expr,
161 AArch64MCExpr::VariantKind &ELFRefKind,
162 MCSymbolRefExpr::VariantKind &DarwinRefKind,
163 int64_t &Addend);
164};
Tim Northover3b0846e2014-05-24 12:50:23 +0000165
166/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
167/// instruction.
168class AArch64Operand : public MCParsedAsmOperand {
169private:
170 enum KindTy {
171 k_Immediate,
172 k_ShiftedImm,
173 k_CondCode,
174 k_Register,
175 k_VectorList,
176 k_VectorIndex,
177 k_Token,
178 k_SysReg,
179 k_SysCR,
180 k_Prefetch,
181 k_ShiftExtend,
182 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000183 k_Barrier,
184 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000185 } Kind;
186
187 SMLoc StartLoc, EndLoc;
188
189 struct TokOp {
190 const char *Data;
191 unsigned Length;
192 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
193 };
194
195 struct RegOp {
196 unsigned RegNum;
197 bool isVector;
198 };
199
200 struct VectorListOp {
201 unsigned RegNum;
202 unsigned Count;
203 unsigned NumElements;
204 unsigned ElementKind;
205 };
206
207 struct VectorIndexOp {
208 unsigned Val;
209 };
210
211 struct ImmOp {
212 const MCExpr *Val;
213 };
214
215 struct ShiftedImmOp {
216 const MCExpr *Val;
217 unsigned ShiftAmount;
218 };
219
220 struct CondCodeOp {
221 AArch64CC::CondCode Code;
222 };
223
224 struct FPImmOp {
225 unsigned Val; // Encoded 8-bit representation.
226 };
227
228 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000229 const char *Data;
230 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000231 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000232 };
233
234 struct SysRegOp {
235 const char *Data;
236 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000237 uint32_t MRSReg;
238 uint32_t MSRReg;
239 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000240 };
241
242 struct SysCRImmOp {
243 unsigned Val;
244 };
245
246 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000247 const char *Data;
248 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000249 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000250 };
251
Oliver Stannarda34e4702015-12-01 10:48:51 +0000252 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000253 const char *Data;
254 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000255 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000256 };
257
Tim Northover3b0846e2014-05-24 12:50:23 +0000258 struct ShiftExtendOp {
259 AArch64_AM::ShiftExtendType Type;
260 unsigned Amount;
261 bool HasExplicitAmount;
262 };
263
264 struct ExtendOp {
265 unsigned Val;
266 };
267
268 union {
269 struct TokOp Tok;
270 struct RegOp Reg;
271 struct VectorListOp VectorList;
272 struct VectorIndexOp VectorIndex;
273 struct ImmOp Imm;
274 struct ShiftedImmOp ShiftedImm;
275 struct CondCodeOp CondCode;
276 struct FPImmOp FPImm;
277 struct BarrierOp Barrier;
278 struct SysRegOp SysReg;
279 struct SysCRImmOp SysCRImm;
280 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000281 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000282 struct ShiftExtendOp ShiftExtend;
283 };
284
285 // Keep the MCContext around as the MCExprs may need manipulated during
286 // the add<>Operands() calls.
287 MCContext &Ctx;
288
David Blaikie960ea3f2014-06-08 16:18:35 +0000289public:
David Blaikie9f380a32015-03-16 18:06:57 +0000290 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000291
Tim Northover3b0846e2014-05-24 12:50:23 +0000292 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
293 Kind = o.Kind;
294 StartLoc = o.StartLoc;
295 EndLoc = o.EndLoc;
296 switch (Kind) {
297 case k_Token:
298 Tok = o.Tok;
299 break;
300 case k_Immediate:
301 Imm = o.Imm;
302 break;
303 case k_ShiftedImm:
304 ShiftedImm = o.ShiftedImm;
305 break;
306 case k_CondCode:
307 CondCode = o.CondCode;
308 break;
309 case k_FPImm:
310 FPImm = o.FPImm;
311 break;
312 case k_Barrier:
313 Barrier = o.Barrier;
314 break;
315 case k_Register:
316 Reg = o.Reg;
317 break;
318 case k_VectorList:
319 VectorList = o.VectorList;
320 break;
321 case k_VectorIndex:
322 VectorIndex = o.VectorIndex;
323 break;
324 case k_SysReg:
325 SysReg = o.SysReg;
326 break;
327 case k_SysCR:
328 SysCRImm = o.SysCRImm;
329 break;
330 case k_Prefetch:
331 Prefetch = o.Prefetch;
332 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000333 case k_PSBHint:
334 PSBHint = o.PSBHint;
335 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000336 case k_ShiftExtend:
337 ShiftExtend = o.ShiftExtend;
338 break;
339 }
340 }
341
342 /// getStartLoc - Get the location of the first token of this operand.
343 SMLoc getStartLoc() const override { return StartLoc; }
344 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000345 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000346
347 StringRef getToken() const {
348 assert(Kind == k_Token && "Invalid access!");
349 return StringRef(Tok.Data, Tok.Length);
350 }
351
352 bool isTokenSuffix() const {
353 assert(Kind == k_Token && "Invalid access!");
354 return Tok.IsSuffix;
355 }
356
357 const MCExpr *getImm() const {
358 assert(Kind == k_Immediate && "Invalid access!");
359 return Imm.Val;
360 }
361
362 const MCExpr *getShiftedImmVal() const {
363 assert(Kind == k_ShiftedImm && "Invalid access!");
364 return ShiftedImm.Val;
365 }
366
367 unsigned getShiftedImmShift() const {
368 assert(Kind == k_ShiftedImm && "Invalid access!");
369 return ShiftedImm.ShiftAmount;
370 }
371
372 AArch64CC::CondCode getCondCode() const {
373 assert(Kind == k_CondCode && "Invalid access!");
374 return CondCode.Code;
375 }
376
377 unsigned getFPImm() const {
378 assert(Kind == k_FPImm && "Invalid access!");
379 return FPImm.Val;
380 }
381
382 unsigned getBarrier() const {
383 assert(Kind == k_Barrier && "Invalid access!");
384 return Barrier.Val;
385 }
386
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000387 StringRef getBarrierName() const {
388 assert(Kind == k_Barrier && "Invalid access!");
389 return StringRef(Barrier.Data, Barrier.Length);
390 }
391
Tim Northover3b0846e2014-05-24 12:50:23 +0000392 unsigned getReg() const override {
393 assert(Kind == k_Register && "Invalid access!");
394 return Reg.RegNum;
395 }
396
397 unsigned getVectorListStart() const {
398 assert(Kind == k_VectorList && "Invalid access!");
399 return VectorList.RegNum;
400 }
401
402 unsigned getVectorListCount() const {
403 assert(Kind == k_VectorList && "Invalid access!");
404 return VectorList.Count;
405 }
406
407 unsigned getVectorIndex() const {
408 assert(Kind == k_VectorIndex && "Invalid access!");
409 return VectorIndex.Val;
410 }
411
412 StringRef getSysReg() const {
413 assert(Kind == k_SysReg && "Invalid access!");
414 return StringRef(SysReg.Data, SysReg.Length);
415 }
416
Tim Northover3b0846e2014-05-24 12:50:23 +0000417 unsigned getSysCR() const {
418 assert(Kind == k_SysCR && "Invalid access!");
419 return SysCRImm.Val;
420 }
421
422 unsigned getPrefetch() const {
423 assert(Kind == k_Prefetch && "Invalid access!");
424 return Prefetch.Val;
425 }
426
Oliver Stannarda34e4702015-12-01 10:48:51 +0000427 unsigned getPSBHint() const {
428 assert(Kind == k_PSBHint && "Invalid access!");
429 return PSBHint.Val;
430 }
431
432 StringRef getPSBHintName() const {
433 assert(Kind == k_PSBHint && "Invalid access!");
434 return StringRef(PSBHint.Data, PSBHint.Length);
435 }
436
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000437 StringRef getPrefetchName() const {
438 assert(Kind == k_Prefetch && "Invalid access!");
439 return StringRef(Prefetch.Data, Prefetch.Length);
440 }
441
Tim Northover3b0846e2014-05-24 12:50:23 +0000442 AArch64_AM::ShiftExtendType getShiftExtendType() const {
443 assert(Kind == k_ShiftExtend && "Invalid access!");
444 return ShiftExtend.Type;
445 }
446
447 unsigned getShiftExtendAmount() const {
448 assert(Kind == k_ShiftExtend && "Invalid access!");
449 return ShiftExtend.Amount;
450 }
451
452 bool hasShiftExtendAmount() const {
453 assert(Kind == k_ShiftExtend && "Invalid access!");
454 return ShiftExtend.HasExplicitAmount;
455 }
456
457 bool isImm() const override { return Kind == k_Immediate; }
458 bool isMem() const override { return false; }
459 bool isSImm9() const {
460 if (!isImm())
461 return false;
462 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
463 if (!MCE)
464 return false;
465 int64_t Val = MCE->getValue();
466 return (Val >= -256 && Val < 256);
467 }
468 bool isSImm7s4() const {
469 if (!isImm())
470 return false;
471 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
472 if (!MCE)
473 return false;
474 int64_t Val = MCE->getValue();
475 return (Val >= -256 && Val <= 252 && (Val & 3) == 0);
476 }
477 bool isSImm7s8() const {
478 if (!isImm())
479 return false;
480 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
481 if (!MCE)
482 return false;
483 int64_t Val = MCE->getValue();
484 return (Val >= -512 && Val <= 504 && (Val & 7) == 0);
485 }
486 bool isSImm7s16() const {
487 if (!isImm())
488 return false;
489 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
490 if (!MCE)
491 return false;
492 int64_t Val = MCE->getValue();
493 return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
494 }
495
496 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
497 AArch64MCExpr::VariantKind ELFRefKind;
498 MCSymbolRefExpr::VariantKind DarwinRefKind;
499 int64_t Addend;
500 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
501 Addend)) {
502 // If we don't understand the expression, assume the best and
503 // let the fixup and relocation code deal with it.
504 return true;
505 }
506
507 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
508 ELFRefKind == AArch64MCExpr::VK_LO12 ||
509 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
510 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
511 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
512 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
513 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
514 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
515 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
516 // Note that we don't range-check the addend. It's adjusted modulo page
517 // size when converted, so there is no "out of range" condition when using
518 // @pageoff.
519 return Addend >= 0 && (Addend % Scale) == 0;
520 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
521 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
522 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
523 return Addend == 0;
524 }
525
526 return false;
527 }
528
529 template <int Scale> bool isUImm12Offset() const {
530 if (!isImm())
531 return false;
532
533 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
534 if (!MCE)
535 return isSymbolicUImm12Offset(getImm(), Scale);
536
537 int64_t Val = MCE->getValue();
538 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
539 }
540
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000541 template <int N, int M>
542 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000543 if (!isImm())
544 return false;
545 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
546 if (!MCE)
547 return false;
548 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000549 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000550 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000551
Tim Northover3b0846e2014-05-24 12:50:23 +0000552 bool isLogicalImm32() const {
553 if (!isImm())
554 return false;
555 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
556 if (!MCE)
557 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000558 int64_t Val = MCE->getValue();
559 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
560 return false;
561 Val &= 0xFFFFFFFF;
562 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000563 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000564
Tim Northover3b0846e2014-05-24 12:50:23 +0000565 bool isLogicalImm64() const {
566 if (!isImm())
567 return false;
568 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
569 if (!MCE)
570 return false;
571 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
572 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000573
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000574 bool isLogicalImm32Not() const {
575 if (!isImm())
576 return false;
577 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
578 if (!MCE)
579 return false;
580 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
581 return AArch64_AM::isLogicalImmediate(Val, 32);
582 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000583
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000584 bool isLogicalImm64Not() const {
585 if (!isImm())
586 return false;
587 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
588 if (!MCE)
589 return false;
590 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
591 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000592
Tim Northover3b0846e2014-05-24 12:50:23 +0000593 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000594
Tim Northover3b0846e2014-05-24 12:50:23 +0000595 bool isAddSubImm() const {
596 if (!isShiftedImm() && !isImm())
597 return false;
598
599 const MCExpr *Expr;
600
601 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
602 if (isShiftedImm()) {
603 unsigned Shift = ShiftedImm.ShiftAmount;
604 Expr = ShiftedImm.Val;
605 if (Shift != 0 && Shift != 12)
606 return false;
607 } else {
608 Expr = getImm();
609 }
610
611 AArch64MCExpr::VariantKind ELFRefKind;
612 MCSymbolRefExpr::VariantKind DarwinRefKind;
613 int64_t Addend;
614 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
615 DarwinRefKind, Addend)) {
616 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
617 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
618 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
619 || ELFRefKind == AArch64MCExpr::VK_LO12
620 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
621 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
622 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
623 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
624 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
625 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
626 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
627 }
628
Diana Picusc93518d2016-10-11 09:17:47 +0000629 // If it's a constant, it should be a real immediate in range:
630 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
631 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
632
633 // If it's an expression, we hope for the best and let the fixup/relocation
634 // code deal with it.
635 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000636 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000637
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000638 bool isAddSubImmNeg() const {
639 if (!isShiftedImm() && !isImm())
640 return false;
641
642 const MCExpr *Expr;
643
644 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
645 if (isShiftedImm()) {
646 unsigned Shift = ShiftedImm.ShiftAmount;
647 Expr = ShiftedImm.Val;
648 if (Shift != 0 && Shift != 12)
649 return false;
650 } else
651 Expr = getImm();
652
653 // Otherwise it should be a real negative immediate in range:
654 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
655 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
656 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000657
Tim Northover3b0846e2014-05-24 12:50:23 +0000658 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000659
Tim Northover3b0846e2014-05-24 12:50:23 +0000660 bool isSIMDImmType10() const {
661 if (!isImm())
662 return false;
663 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
664 if (!MCE)
665 return false;
666 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
667 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000668
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000669 template<int N>
670 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000671 if (!isImm())
672 return false;
673 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
674 if (!MCE)
675 return true;
676 int64_t Val = MCE->getValue();
677 if (Val & 0x3)
678 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000679 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
680 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000681 }
682
683 bool
684 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
685 if (!isImm())
686 return false;
687
688 AArch64MCExpr::VariantKind ELFRefKind;
689 MCSymbolRefExpr::VariantKind DarwinRefKind;
690 int64_t Addend;
691 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
692 DarwinRefKind, Addend)) {
693 return false;
694 }
695 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
696 return false;
697
698 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
699 if (ELFRefKind == AllowedModifiers[i])
700 return Addend == 0;
701 }
702
703 return false;
704 }
705
706 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000707 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000708 }
709
710 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000711 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
712 AArch64MCExpr::VK_TPREL_G2,
713 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000714 }
715
716 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000717 return isMovWSymbol({
718 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000719 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
720 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000721 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000722 }
723
724 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000725 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
726 AArch64MCExpr::VK_TPREL_G0,
727 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000728 }
729
730 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000731 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000732 }
733
734 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000735 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000736 }
737
738 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000739 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
740 AArch64MCExpr::VK_TPREL_G1_NC,
741 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000742 }
743
744 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000745 return isMovWSymbol(
746 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
747 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000748 }
749
750 template<int RegWidth, int Shift>
751 bool isMOVZMovAlias() const {
752 if (!isImm()) return false;
753
754 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
755 if (!CE) return false;
756 uint64_t Value = CE->getValue();
757
Tim Northoverdaa1c012016-06-16 01:42:25 +0000758 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000759 }
760
761 template<int RegWidth, int Shift>
762 bool isMOVNMovAlias() const {
763 if (!isImm()) return false;
764
765 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
766 if (!CE) return false;
767 uint64_t Value = CE->getValue();
768
Tim Northoverdaa1c012016-06-16 01:42:25 +0000769 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000770 }
771
772 bool isFPImm() const { return Kind == k_FPImm; }
773 bool isBarrier() const { return Kind == k_Barrier; }
774 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000775
Tim Northover3b0846e2014-05-24 12:50:23 +0000776 bool isMRSSystemRegister() const {
777 if (!isSysReg()) return false;
778
Tim Northover7cd58932015-01-22 17:23:04 +0000779 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000780 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000781
Tim Northover3b0846e2014-05-24 12:50:23 +0000782 bool isMSRSystemRegister() const {
783 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000784 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000785 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000786
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000787 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000788 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000789 return (SysReg.PStateField == AArch64PState::PAN ||
790 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000791 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000792
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000793 bool isSystemPStateFieldWithImm0_15() const {
794 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000795 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000796 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000797
Tim Northover3b0846e2014-05-24 12:50:23 +0000798 bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
799 bool isVectorReg() const { return Kind == k_Register && Reg.isVector; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000800
Tim Northover3b0846e2014-05-24 12:50:23 +0000801 bool isVectorRegLo() const {
802 return Kind == k_Register && Reg.isVector &&
803 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
804 Reg.RegNum);
805 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000806
Tim Northover3b0846e2014-05-24 12:50:23 +0000807 bool isGPR32as64() const {
808 return Kind == k_Register && !Reg.isVector &&
809 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
810 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000811
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000812 bool isWSeqPair() const {
813 return Kind == k_Register && !Reg.isVector &&
814 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
815 Reg.RegNum);
816 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000817
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000818 bool isXSeqPair() const {
819 return Kind == k_Register && !Reg.isVector &&
820 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
821 Reg.RegNum);
822 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000823
824 bool isGPR64sp0() const {
825 return Kind == k_Register && !Reg.isVector &&
826 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
827 }
828
829 /// Is this a vector list with the type implicit (presumably attached to the
830 /// instruction itself)?
831 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
832 return Kind == k_VectorList && VectorList.Count == NumRegs &&
833 !VectorList.ElementKind;
834 }
835
836 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
837 bool isTypedVectorList() const {
838 if (Kind != k_VectorList)
839 return false;
840 if (VectorList.Count != NumRegs)
841 return false;
842 if (VectorList.ElementKind != ElementKind)
843 return false;
844 return VectorList.NumElements == NumElements;
845 }
846
847 bool isVectorIndex1() const {
848 return Kind == k_VectorIndex && VectorIndex.Val == 1;
849 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000850
Tim Northover3b0846e2014-05-24 12:50:23 +0000851 bool isVectorIndexB() const {
852 return Kind == k_VectorIndex && VectorIndex.Val < 16;
853 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000854
Tim Northover3b0846e2014-05-24 12:50:23 +0000855 bool isVectorIndexH() const {
856 return Kind == k_VectorIndex && VectorIndex.Val < 8;
857 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000858
Tim Northover3b0846e2014-05-24 12:50:23 +0000859 bool isVectorIndexS() const {
860 return Kind == k_VectorIndex && VectorIndex.Val < 4;
861 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000862
Tim Northover3b0846e2014-05-24 12:50:23 +0000863 bool isVectorIndexD() const {
864 return Kind == k_VectorIndex && VectorIndex.Val < 2;
865 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000866
Tim Northover3b0846e2014-05-24 12:50:23 +0000867 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000868
Tim Northover3b0846e2014-05-24 12:50:23 +0000869 bool isTokenEqual(StringRef Str) const {
870 return Kind == k_Token && getToken() == Str;
871 }
872 bool isSysCR() const { return Kind == k_SysCR; }
873 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000874 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000875 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
876 bool isShifter() const {
877 if (!isShiftExtend())
878 return false;
879
880 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
881 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
882 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
883 ST == AArch64_AM::MSL);
884 }
885 bool isExtend() const {
886 if (!isShiftExtend())
887 return false;
888
889 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
890 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
891 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
892 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
893 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
894 ET == AArch64_AM::LSL) &&
895 getShiftExtendAmount() <= 4;
896 }
897
898 bool isExtend64() const {
899 if (!isExtend())
900 return false;
901 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
902 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
903 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
904 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000905
Tim Northover3b0846e2014-05-24 12:50:23 +0000906 bool isExtendLSL64() const {
907 if (!isExtend())
908 return false;
909 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
910 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
911 ET == AArch64_AM::LSL) &&
912 getShiftExtendAmount() <= 4;
913 }
914
915 template<int Width> bool isMemXExtend() const {
916 if (!isExtend())
917 return false;
918 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
919 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
920 (getShiftExtendAmount() == Log2_32(Width / 8) ||
921 getShiftExtendAmount() == 0);
922 }
923
924 template<int Width> bool isMemWExtend() const {
925 if (!isExtend())
926 return false;
927 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
928 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
929 (getShiftExtendAmount() == Log2_32(Width / 8) ||
930 getShiftExtendAmount() == 0);
931 }
932
933 template <unsigned width>
934 bool isArithmeticShifter() const {
935 if (!isShifter())
936 return false;
937
938 // An arithmetic shifter is LSL, LSR, or ASR.
939 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
940 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
941 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
942 }
943
944 template <unsigned width>
945 bool isLogicalShifter() const {
946 if (!isShifter())
947 return false;
948
949 // A logical shifter is LSL, LSR, ASR or ROR.
950 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
951 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
952 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
953 getShiftExtendAmount() < width;
954 }
955
956 bool isMovImm32Shifter() const {
957 if (!isShifter())
958 return false;
959
960 // A MOVi shifter is LSL of 0, 16, 32, or 48.
961 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
962 if (ST != AArch64_AM::LSL)
963 return false;
964 uint64_t Val = getShiftExtendAmount();
965 return (Val == 0 || Val == 16);
966 }
967
968 bool isMovImm64Shifter() const {
969 if (!isShifter())
970 return false;
971
972 // A MOVi shifter is LSL of 0 or 16.
973 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
974 if (ST != AArch64_AM::LSL)
975 return false;
976 uint64_t Val = getShiftExtendAmount();
977 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
978 }
979
980 bool isLogicalVecShifter() const {
981 if (!isShifter())
982 return false;
983
984 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
985 unsigned Shift = getShiftExtendAmount();
986 return getShiftExtendType() == AArch64_AM::LSL &&
987 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
988 }
989
990 bool isLogicalVecHalfWordShifter() const {
991 if (!isLogicalVecShifter())
992 return false;
993
994 // A logical vector shifter is a left shift by 0 or 8.
995 unsigned Shift = getShiftExtendAmount();
996 return getShiftExtendType() == AArch64_AM::LSL &&
997 (Shift == 0 || Shift == 8);
998 }
999
1000 bool isMoveVecShifter() const {
1001 if (!isShiftExtend())
1002 return false;
1003
1004 // A logical vector shifter is a left shift by 8 or 16.
1005 unsigned Shift = getShiftExtendAmount();
1006 return getShiftExtendType() == AArch64_AM::MSL &&
1007 (Shift == 8 || Shift == 16);
1008 }
1009
1010 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1011 // to LDUR/STUR when the offset is not legal for the former but is for
1012 // the latter. As such, in addition to checking for being a legal unscaled
1013 // address, also check that it is not a legal scaled address. This avoids
1014 // ambiguity in the matcher.
1015 template<int Width>
1016 bool isSImm9OffsetFB() const {
1017 return isSImm9() && !isUImm12Offset<Width / 8>();
1018 }
1019
1020 bool isAdrpLabel() const {
1021 // Validation was handled during parsing, so we just sanity check that
1022 // something didn't go haywire.
1023 if (!isImm())
1024 return false;
1025
1026 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1027 int64_t Val = CE->getValue();
1028 int64_t Min = - (4096 * (1LL << (21 - 1)));
1029 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1030 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1031 }
1032
1033 return true;
1034 }
1035
1036 bool isAdrLabel() const {
1037 // Validation was handled during parsing, so we just sanity check that
1038 // something didn't go haywire.
1039 if (!isImm())
1040 return false;
1041
1042 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1043 int64_t Val = CE->getValue();
1044 int64_t Min = - (1LL << (21 - 1));
1045 int64_t Max = ((1LL << (21 - 1)) - 1);
1046 return Val >= Min && Val <= Max;
1047 }
1048
1049 return true;
1050 }
1051
1052 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1053 // Add as immediates when possible. Null MCExpr = 0.
1054 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001055 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001056 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001057 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001058 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001059 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001060 }
1061
1062 void addRegOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001064 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001065 }
1066
1067 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
1069 assert(
1070 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1071
1072 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1073 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1074 RI->getEncodingValue(getReg()));
1075
Jim Grosbache9119e42015-05-13 18:37:00 +00001076 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001077 }
1078
1079 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1080 assert(N == 1 && "Invalid number of operands!");
1081 assert(
1082 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001083 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001084 }
1085
1086 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1087 assert(N == 1 && "Invalid number of operands!");
1088 assert(
1089 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001090 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001091 }
1092
1093 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1094 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001095 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001096 }
1097
1098 template <unsigned NumRegs>
1099 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1100 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001101 static const unsigned FirstRegs[] = { AArch64::D0,
1102 AArch64::D0_D1,
1103 AArch64::D0_D1_D2,
1104 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001105 unsigned FirstReg = FirstRegs[NumRegs - 1];
1106
1107 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001108 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001109 }
1110
1111 template <unsigned NumRegs>
1112 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1113 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001114 static const unsigned FirstRegs[] = { AArch64::Q0,
1115 AArch64::Q0_Q1,
1116 AArch64::Q0_Q1_Q2,
1117 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001118 unsigned FirstReg = FirstRegs[NumRegs - 1];
1119
1120 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001121 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001122 }
1123
1124 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1125 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001126 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001127 }
1128
1129 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001131 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001132 }
1133
1134 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001136 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001137 }
1138
1139 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1140 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001141 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001142 }
1143
1144 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1145 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001146 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001147 }
1148
1149 void addImmOperands(MCInst &Inst, unsigned N) const {
1150 assert(N == 1 && "Invalid number of operands!");
1151 // If this is a pageoff symrefexpr with an addend, adjust the addend
1152 // to be only the page-offset portion. Otherwise, just add the expr
1153 // as-is.
1154 addExpr(Inst, getImm());
1155 }
1156
1157 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1158 assert(N == 2 && "Invalid number of operands!");
1159 if (isShiftedImm()) {
1160 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001161 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001162 } else {
1163 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001164 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001165 }
1166 }
1167
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001168 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1169 assert(N == 2 && "Invalid number of operands!");
1170
1171 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1172 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1173 int64_t Val = -CE->getValue();
1174 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1175
1176 Inst.addOperand(MCOperand::createImm(Val));
1177 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1178 }
1179
Tim Northover3b0846e2014-05-24 12:50:23 +00001180 void addCondCodeOperands(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(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001183 }
1184
1185 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1186 assert(N == 1 && "Invalid number of operands!");
1187 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1188 if (!MCE)
1189 addExpr(Inst, getImm());
1190 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001191 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001192 }
1193
1194 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1195 addImmOperands(Inst, N);
1196 }
1197
1198 template<int Scale>
1199 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1200 assert(N == 1 && "Invalid number of operands!");
1201 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1202
1203 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001204 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001205 return;
1206 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001207 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001208 }
1209
1210 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1211 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001212 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001213 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001214 }
1215
1216 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1217 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001218 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001219 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001220 }
1221
1222 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1223 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001224 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001225 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001226 }
1227
1228 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1229 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001230 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001231 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001232 }
1233
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001234 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1235 assert(N == 1 && "Invalid number of operands!");
1236 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1237 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1238 }
1239
Tim Northover3b0846e2014-05-24 12:50:23 +00001240 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1241 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001242 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001243 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001244 }
1245
1246 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1247 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001248 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001249 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001250 }
1251
1252 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1253 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001254 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001255 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001256 }
1257
1258 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1259 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001260 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001261 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001262 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001263 }
1264
1265 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1266 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001267 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001268 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001269 }
1270
1271 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001273 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001274 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001275 }
1276
1277 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1278 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001279 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001280 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001281 }
1282
1283 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1284 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001285 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001286 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001287 }
1288
1289 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001291 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001292 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001293 }
1294
1295 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001297 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001298 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001299 }
1300
1301 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1302 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001303 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001304 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001305 }
1306
1307 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1308 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001309 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001310 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001311 }
1312
1313 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1314 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001315 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001316 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001317 }
1318
1319 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1320 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001321 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001322 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001323 }
1324
1325 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1326 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001327 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001328 uint64_t encoding =
1329 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 }
1332
1333 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001335 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001336 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001337 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001340 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
1342 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1343 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1344 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001345 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001346 }
1347
1348 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
1350 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1351 uint64_t encoding =
1352 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001353 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001354 }
1355
Tim Northover3b0846e2014-05-24 12:50:23 +00001356 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1357 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001358 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001359 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001360 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001361 }
1362
1363 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1364 // Branch operands don't encode the low bits, so shift them off
1365 // here. If it's a label, however, just put it on directly as there's
1366 // not enough information now to do anything.
1367 assert(N == 1 && "Invalid number of operands!");
1368 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1369 if (!MCE) {
1370 addExpr(Inst, getImm());
1371 return;
1372 }
1373 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001374 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001375 }
1376
1377 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1378 // Branch operands don't encode the low bits, so shift them off
1379 // here. If it's a label, however, just put it on directly as there's
1380 // not enough information now to do anything.
1381 assert(N == 1 && "Invalid number of operands!");
1382 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1383 if (!MCE) {
1384 addExpr(Inst, getImm());
1385 return;
1386 }
1387 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001388 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001389 }
1390
1391 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1392 // Branch operands don't encode the low bits, so shift them off
1393 // here. If it's a label, however, just put it on directly as there's
1394 // not enough information now to do anything.
1395 assert(N == 1 && "Invalid number of operands!");
1396 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1397 if (!MCE) {
1398 addExpr(Inst, getImm());
1399 return;
1400 }
1401 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001402 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001403 }
1404
1405 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1406 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001407 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001408 }
1409
1410 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1411 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001412 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001413 }
1414
1415 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1416 assert(N == 1 && "Invalid number of operands!");
1417
Jim Grosbache9119e42015-05-13 18:37:00 +00001418 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001419 }
1420
1421 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1422 assert(N == 1 && "Invalid number of operands!");
1423
Jim Grosbache9119e42015-05-13 18:37:00 +00001424 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001425 }
1426
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001427 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1428 assert(N == 1 && "Invalid number of operands!");
1429
1430 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1431 }
1432
1433 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 assert(N == 1 && "Invalid number of operands!");
1435
Jim Grosbache9119e42015-05-13 18:37:00 +00001436 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001437 }
1438
1439 void addSysCROperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001441 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001442 }
1443
1444 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001446 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001447 }
1448
Oliver Stannarda34e4702015-12-01 10:48:51 +00001449 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
1451 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1452 }
1453
Tim Northover3b0846e2014-05-24 12:50:23 +00001454 void addShifterOperands(MCInst &Inst, unsigned N) const {
1455 assert(N == 1 && "Invalid number of operands!");
1456 unsigned Imm =
1457 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001458 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 }
1460
1461 void addExtendOperands(MCInst &Inst, unsigned N) const {
1462 assert(N == 1 && "Invalid number of operands!");
1463 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1464 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1465 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001466 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001467 }
1468
1469 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1470 assert(N == 1 && "Invalid number of operands!");
1471 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1472 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1473 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001474 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001475 }
1476
1477 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 2 && "Invalid number of operands!");
1479 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1480 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createImm(IsSigned));
1482 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001483 }
1484
1485 // For 8-bit load/store instructions with a register offset, both the
1486 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1487 // they're disambiguated by whether the shift was explicit or implicit rather
1488 // than its size.
1489 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1490 assert(N == 2 && "Invalid number of operands!");
1491 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1492 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001493 Inst.addOperand(MCOperand::createImm(IsSigned));
1494 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001495 }
1496
1497 template<int Shift>
1498 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1499 assert(N == 1 && "Invalid number of operands!");
1500
1501 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1502 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001503 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
1506 template<int Shift>
1507 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
1509
1510 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1511 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001512 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001513 }
1514
1515 void print(raw_ostream &OS) const override;
1516
David Blaikie960ea3f2014-06-08 16:18:35 +00001517 static std::unique_ptr<AArch64Operand>
1518 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1519 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001520 Op->Tok.Data = Str.data();
1521 Op->Tok.Length = Str.size();
1522 Op->Tok.IsSuffix = IsSuffix;
1523 Op->StartLoc = S;
1524 Op->EndLoc = S;
1525 return Op;
1526 }
1527
David Blaikie960ea3f2014-06-08 16:18:35 +00001528 static std::unique_ptr<AArch64Operand>
1529 CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
1530 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001531 Op->Reg.RegNum = RegNum;
1532 Op->Reg.isVector = isVector;
1533 Op->StartLoc = S;
1534 Op->EndLoc = E;
1535 return Op;
1536 }
1537
David Blaikie960ea3f2014-06-08 16:18:35 +00001538 static std::unique_ptr<AArch64Operand>
1539 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1540 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1541 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001542 Op->VectorList.RegNum = RegNum;
1543 Op->VectorList.Count = Count;
1544 Op->VectorList.NumElements = NumElements;
1545 Op->VectorList.ElementKind = ElementKind;
1546 Op->StartLoc = S;
1547 Op->EndLoc = E;
1548 return Op;
1549 }
1550
David Blaikie960ea3f2014-06-08 16:18:35 +00001551 static std::unique_ptr<AArch64Operand>
1552 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1553 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001554 Op->VectorIndex.Val = Idx;
1555 Op->StartLoc = S;
1556 Op->EndLoc = E;
1557 return Op;
1558 }
1559
David Blaikie960ea3f2014-06-08 16:18:35 +00001560 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1561 SMLoc E, MCContext &Ctx) {
1562 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001563 Op->Imm.Val = Val;
1564 Op->StartLoc = S;
1565 Op->EndLoc = E;
1566 return Op;
1567 }
1568
David Blaikie960ea3f2014-06-08 16:18:35 +00001569 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1570 unsigned ShiftAmount,
1571 SMLoc S, SMLoc E,
1572 MCContext &Ctx) {
1573 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001574 Op->ShiftedImm .Val = Val;
1575 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1576 Op->StartLoc = S;
1577 Op->EndLoc = E;
1578 return Op;
1579 }
1580
David Blaikie960ea3f2014-06-08 16:18:35 +00001581 static std::unique_ptr<AArch64Operand>
1582 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1583 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001584 Op->CondCode.Code = Code;
1585 Op->StartLoc = S;
1586 Op->EndLoc = E;
1587 return Op;
1588 }
1589
David Blaikie960ea3f2014-06-08 16:18:35 +00001590 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1591 MCContext &Ctx) {
1592 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001593 Op->FPImm.Val = Val;
1594 Op->StartLoc = S;
1595 Op->EndLoc = S;
1596 return Op;
1597 }
1598
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001599 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1600 StringRef Str,
1601 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001602 MCContext &Ctx) {
1603 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001604 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001605 Op->Barrier.Data = Str.data();
1606 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001607 Op->StartLoc = S;
1608 Op->EndLoc = S;
1609 return Op;
1610 }
1611
Tim Northover7cd58932015-01-22 17:23:04 +00001612 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1613 uint32_t MRSReg,
1614 uint32_t MSRReg,
1615 uint32_t PStateField,
1616 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001617 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001618 Op->SysReg.Data = Str.data();
1619 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001620 Op->SysReg.MRSReg = MRSReg;
1621 Op->SysReg.MSRReg = MSRReg;
1622 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001623 Op->StartLoc = S;
1624 Op->EndLoc = S;
1625 return Op;
1626 }
1627
David Blaikie960ea3f2014-06-08 16:18:35 +00001628 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1629 SMLoc E, MCContext &Ctx) {
1630 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001631 Op->SysCRImm.Val = Val;
1632 Op->StartLoc = S;
1633 Op->EndLoc = E;
1634 return Op;
1635 }
1636
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001637 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1638 StringRef Str,
1639 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001640 MCContext &Ctx) {
1641 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001642 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001643 Op->Barrier.Data = Str.data();
1644 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001645 Op->StartLoc = S;
1646 Op->EndLoc = S;
1647 return Op;
1648 }
1649
Oliver Stannarda34e4702015-12-01 10:48:51 +00001650 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1651 StringRef Str,
1652 SMLoc S,
1653 MCContext &Ctx) {
1654 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1655 Op->PSBHint.Val = Val;
1656 Op->PSBHint.Data = Str.data();
1657 Op->PSBHint.Length = Str.size();
1658 Op->StartLoc = S;
1659 Op->EndLoc = S;
1660 return Op;
1661 }
1662
David Blaikie960ea3f2014-06-08 16:18:35 +00001663 static std::unique_ptr<AArch64Operand>
1664 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1665 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1666 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->ShiftExtend.Type = ShOp;
1668 Op->ShiftExtend.Amount = Val;
1669 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1670 Op->StartLoc = S;
1671 Op->EndLoc = E;
1672 return Op;
1673 }
1674};
1675
1676} // end anonymous namespace.
1677
1678void AArch64Operand::print(raw_ostream &OS) const {
1679 switch (Kind) {
1680 case k_FPImm:
1681 OS << "<fpimm " << getFPImm() << "("
1682 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1683 break;
1684 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001685 StringRef Name = getBarrierName();
1686 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001687 OS << "<barrier " << Name << ">";
1688 else
1689 OS << "<barrier invalid #" << getBarrier() << ">";
1690 break;
1691 }
1692 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001693 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001694 break;
1695 case k_ShiftedImm: {
1696 unsigned Shift = getShiftedImmShift();
1697 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001698 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001699 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1700 break;
1701 }
1702 case k_CondCode:
1703 OS << "<condcode " << getCondCode() << ">";
1704 break;
1705 case k_Register:
1706 OS << "<register " << getReg() << ">";
1707 break;
1708 case k_VectorList: {
1709 OS << "<vectorlist ";
1710 unsigned Reg = getVectorListStart();
1711 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1712 OS << Reg + i << " ";
1713 OS << ">";
1714 break;
1715 }
1716 case k_VectorIndex:
1717 OS << "<vectorindex " << getVectorIndex() << ">";
1718 break;
1719 case k_SysReg:
1720 OS << "<sysreg: " << getSysReg() << '>';
1721 break;
1722 case k_Token:
1723 OS << "'" << getToken() << "'";
1724 break;
1725 case k_SysCR:
1726 OS << "c" << getSysCR();
1727 break;
1728 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001729 StringRef Name = getPrefetchName();
1730 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001731 OS << "<prfop " << Name << ">";
1732 else
1733 OS << "<prfop invalid #" << getPrefetch() << ">";
1734 break;
1735 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001736 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001737 OS << getPSBHintName();
1738 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001739 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001740 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1741 << getShiftExtendAmount();
1742 if (!hasShiftExtendAmount())
1743 OS << "<imp>";
1744 OS << '>';
1745 break;
1746 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001747}
1748
1749/// @name Auto-generated Match Functions
1750/// {
1751
1752static unsigned MatchRegisterName(StringRef Name);
1753
1754/// }
1755
1756static unsigned matchVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001757 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001758 .Case("v0", AArch64::Q0)
1759 .Case("v1", AArch64::Q1)
1760 .Case("v2", AArch64::Q2)
1761 .Case("v3", AArch64::Q3)
1762 .Case("v4", AArch64::Q4)
1763 .Case("v5", AArch64::Q5)
1764 .Case("v6", AArch64::Q6)
1765 .Case("v7", AArch64::Q7)
1766 .Case("v8", AArch64::Q8)
1767 .Case("v9", AArch64::Q9)
1768 .Case("v10", AArch64::Q10)
1769 .Case("v11", AArch64::Q11)
1770 .Case("v12", AArch64::Q12)
1771 .Case("v13", AArch64::Q13)
1772 .Case("v14", AArch64::Q14)
1773 .Case("v15", AArch64::Q15)
1774 .Case("v16", AArch64::Q16)
1775 .Case("v17", AArch64::Q17)
1776 .Case("v18", AArch64::Q18)
1777 .Case("v19", AArch64::Q19)
1778 .Case("v20", AArch64::Q20)
1779 .Case("v21", AArch64::Q21)
1780 .Case("v22", AArch64::Q22)
1781 .Case("v23", AArch64::Q23)
1782 .Case("v24", AArch64::Q24)
1783 .Case("v25", AArch64::Q25)
1784 .Case("v26", AArch64::Q26)
1785 .Case("v27", AArch64::Q27)
1786 .Case("v28", AArch64::Q28)
1787 .Case("v29", AArch64::Q29)
1788 .Case("v30", AArch64::Q30)
1789 .Case("v31", AArch64::Q31)
1790 .Default(0);
1791}
1792
1793static bool isValidVectorKind(StringRef Name) {
1794 return StringSwitch<bool>(Name.lower())
1795 .Case(".8b", true)
1796 .Case(".16b", true)
1797 .Case(".4h", true)
1798 .Case(".8h", true)
1799 .Case(".2s", true)
1800 .Case(".4s", true)
1801 .Case(".1d", true)
1802 .Case(".2d", true)
1803 .Case(".1q", true)
1804 // Accept the width neutral ones, too, for verbose syntax. If those
1805 // aren't used in the right places, the token operand won't match so
1806 // all will work out.
1807 .Case(".b", true)
1808 .Case(".h", true)
1809 .Case(".s", true)
1810 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001811 // Needed for fp16 scalar pairwise reductions
1812 .Case(".2h", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001813 .Default(false);
1814}
1815
1816static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1817 char &ElementKind) {
1818 assert(isValidVectorKind(Name));
1819
1820 ElementKind = Name.lower()[Name.size() - 1];
1821 NumElements = 0;
1822
1823 if (Name.size() == 2)
1824 return;
1825
1826 // Parse the lane count
1827 Name = Name.drop_front();
1828 while (isdigit(Name.front())) {
1829 NumElements = 10 * NumElements + (Name.front() - '0');
1830 Name = Name.drop_front();
1831 }
1832}
1833
1834bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1835 SMLoc &EndLoc) {
1836 StartLoc = getLoc();
1837 RegNo = tryParseRegister();
1838 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1839 return (RegNo == (unsigned)-1);
1840}
1841
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001842// Matches a register name or register alias previously defined by '.req'
1843unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
1844 bool isVector) {
1845 unsigned RegNum = isVector ? matchVectorRegName(Name)
1846 : MatchRegisterName(Name);
1847
1848 if (RegNum == 0) {
1849 // Check for aliases registered via .req. Canonicalize to lower case.
1850 // That's more consistent since register names are case insensitive, and
1851 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1852 auto Entry = RegisterReqs.find(Name.lower());
1853 if (Entry == RegisterReqs.end())
1854 return 0;
1855 // set RegNum if the match is the right kind of register
1856 if (isVector == Entry->getValue().first)
1857 RegNum = Entry->getValue().second;
1858 }
1859 return RegNum;
1860}
1861
Tim Northover3b0846e2014-05-24 12:50:23 +00001862/// tryParseRegister - Try to parse a register name. The token must be an
1863/// Identifier when called, and if it is a register name the token is eaten and
1864/// the register is added to the operand list.
1865int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001866 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001867 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001868 if (Tok.isNot(AsmToken::Identifier))
1869 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00001870
1871 std::string lowerCase = Tok.getString().lower();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001872 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
Tim Northover3b0846e2014-05-24 12:50:23 +00001873 // Also handle a few aliases of registers.
1874 if (RegNum == 0)
1875 RegNum = StringSwitch<unsigned>(lowerCase)
1876 .Case("fp", AArch64::FP)
1877 .Case("lr", AArch64::LR)
1878 .Case("x31", AArch64::XZR)
1879 .Case("w31", AArch64::WZR)
1880 .Default(0);
1881
1882 if (RegNum == 0)
1883 return -1;
1884
1885 Parser.Lex(); // Eat identifier token.
1886 return RegNum;
1887}
1888
1889/// tryMatchVectorRegister - Try to parse a vector register name with optional
1890/// kind specifier. If it is a register specifier, eat the token and return it.
1891int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001892 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001893 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1894 TokError("vector register expected");
1895 return -1;
1896 }
1897
1898 StringRef Name = Parser.getTok().getString();
1899 // If there is a kind specifier, it's separated from the register name by
1900 // a '.'.
1901 size_t Start = 0, Next = Name.find('.');
1902 StringRef Head = Name.slice(Start, Next);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001903 unsigned RegNum = matchRegisterNameAlias(Head, true);
1904
Tim Northover3b0846e2014-05-24 12:50:23 +00001905 if (RegNum) {
1906 if (Next != StringRef::npos) {
1907 Kind = Name.slice(Next, StringRef::npos);
1908 if (!isValidVectorKind(Kind)) {
1909 TokError("invalid vector kind qualifier");
1910 return -1;
1911 }
1912 }
1913 Parser.Lex(); // Eat the register token.
1914 return RegNum;
1915 }
1916
1917 if (expected)
1918 TokError("vector register expected");
1919 return -1;
1920}
1921
1922/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00001923OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001924AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001925 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001926 SMLoc S = getLoc();
1927
1928 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1929 Error(S, "Expected cN operand where 0 <= N <= 15");
1930 return MatchOperand_ParseFail;
1931 }
1932
1933 StringRef Tok = Parser.getTok().getIdentifier();
1934 if (Tok[0] != 'c' && Tok[0] != 'C') {
1935 Error(S, "Expected cN operand where 0 <= N <= 15");
1936 return MatchOperand_ParseFail;
1937 }
1938
1939 uint32_t CRNum;
1940 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
1941 if (BadNum || CRNum > 15) {
1942 Error(S, "Expected cN operand where 0 <= N <= 15");
1943 return MatchOperand_ParseFail;
1944 }
1945
1946 Parser.Lex(); // Eat identifier token.
1947 Operands.push_back(
1948 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
1949 return MatchOperand_Success;
1950}
1951
1952/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00001953OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001954AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001955 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001956 SMLoc S = getLoc();
1957 const AsmToken &Tok = Parser.getTok();
1958 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00001959 // Eat optional hash.
1960 if (parseOptionalToken(AsmToken::Hash) ||
1961 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001962 const MCExpr *ImmVal;
1963 if (getParser().parseExpression(ImmVal))
1964 return MatchOperand_ParseFail;
1965
1966 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1967 if (!MCE) {
1968 TokError("immediate value expected for prefetch operand");
1969 return MatchOperand_ParseFail;
1970 }
1971 unsigned prfop = MCE->getValue();
1972 if (prfop > 31) {
1973 TokError("prefetch operand out of range, [0,31] expected");
1974 return MatchOperand_ParseFail;
1975 }
1976
Tim Northovere6ae6762016-07-05 21:23:04 +00001977 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
1978 Operands.push_back(AArch64Operand::CreatePrefetch(
1979 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001980 return MatchOperand_Success;
1981 }
1982
1983 if (Tok.isNot(AsmToken::Identifier)) {
1984 TokError("pre-fetch hint expected");
1985 return MatchOperand_ParseFail;
1986 }
1987
Tim Northovere6ae6762016-07-05 21:23:04 +00001988 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
1989 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001990 TokError("pre-fetch hint expected");
1991 return MatchOperand_ParseFail;
1992 }
1993
1994 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00001995 Operands.push_back(AArch64Operand::CreatePrefetch(
1996 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001997 return MatchOperand_Success;
1998}
1999
Oliver Stannarda34e4702015-12-01 10:48:51 +00002000/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002001OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002002AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2003 MCAsmParser &Parser = getParser();
2004 SMLoc S = getLoc();
2005 const AsmToken &Tok = Parser.getTok();
2006 if (Tok.isNot(AsmToken::Identifier)) {
2007 TokError("invalid operand for instruction");
2008 return MatchOperand_ParseFail;
2009 }
2010
Tim Northovere6ae6762016-07-05 21:23:04 +00002011 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2012 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002013 TokError("invalid operand for instruction");
2014 return MatchOperand_ParseFail;
2015 }
2016
2017 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002018 Operands.push_back(AArch64Operand::CreatePSBHint(
2019 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002020 return MatchOperand_Success;
2021}
2022
Tim Northover3b0846e2014-05-24 12:50:23 +00002023/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2024/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002025OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002026AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002027 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002028 SMLoc S = getLoc();
2029 const MCExpr *Expr;
2030
2031 if (Parser.getTok().is(AsmToken::Hash)) {
2032 Parser.Lex(); // Eat hash token.
2033 }
2034
2035 if (parseSymbolicImmVal(Expr))
2036 return MatchOperand_ParseFail;
2037
2038 AArch64MCExpr::VariantKind ELFRefKind;
2039 MCSymbolRefExpr::VariantKind DarwinRefKind;
2040 int64_t Addend;
2041 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2042 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2043 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2044 // No modifier was specified at all; this is the syntax for an ELF basic
2045 // ADRP relocation (unfortunately).
2046 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002047 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002048 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2049 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2050 Addend != 0) {
2051 Error(S, "gotpage label reference not allowed an addend");
2052 return MatchOperand_ParseFail;
2053 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2054 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2055 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2056 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2057 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2058 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2059 // The operand must be an @page or @gotpage qualified symbolref.
2060 Error(S, "page or gotpage label reference expected");
2061 return MatchOperand_ParseFail;
2062 }
2063 }
2064
2065 // We have either a label reference possibly with addend or an immediate. The
2066 // addend is a raw value here. The linker will adjust it to only reference the
2067 // page.
2068 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2069 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2070
2071 return MatchOperand_Success;
2072}
2073
2074/// tryParseAdrLabel - Parse and validate a source label for the ADR
2075/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002076OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002077AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2078 SMLoc S = getLoc();
2079 const MCExpr *Expr;
2080
Nirav Davee833c6c2016-11-08 18:31:04 +00002081 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002082 if (getParser().parseExpression(Expr))
2083 return MatchOperand_ParseFail;
2084
2085 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2086 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2087
2088 return MatchOperand_Success;
2089}
2090
2091/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002092OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002093AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002094 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002095 SMLoc S = getLoc();
2096
Nirav Davee833c6c2016-11-08 18:31:04 +00002097 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002098
2099 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002100 bool isNegative = parseOptionalToken(AsmToken::Minus);
2101
Tim Northover3b0846e2014-05-24 12:50:23 +00002102 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002103 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002104 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002105 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002106 Val = Tok.getIntVal();
2107 if (Val > 255 || Val < 0) {
2108 TokError("encoded floating point value out of range");
2109 return MatchOperand_ParseFail;
2110 }
2111 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002112 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002113 if (isNegative)
2114 RealVal.changeSign();
2115
Tim Northover3b0846e2014-05-24 12:50:23 +00002116 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002117 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002118
John Brawn5ca5daa2017-04-20 10:13:54 +00002119 // Check for out of range values. As an exception we let Zero through,
2120 // but as tokens instead of an FPImm so that it can be matched by the
2121 // appropriate alias if one exists.
2122 if (RealVal.isPosZero()) {
2123 Parser.Lex(); // Eat the token.
2124 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2125 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2126 return MatchOperand_Success;
2127 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002128 TokError("expected compatible register or floating-point constant");
2129 return MatchOperand_ParseFail;
2130 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002131 }
2132 Parser.Lex(); // Eat the token.
2133 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2134 return MatchOperand_Success;
2135 }
2136
2137 if (!Hash)
2138 return MatchOperand_NoMatch;
2139
2140 TokError("invalid floating point immediate");
2141 return MatchOperand_ParseFail;
2142}
2143
2144/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002145OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002146AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002147 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002148 SMLoc S = getLoc();
2149
2150 if (Parser.getTok().is(AsmToken::Hash))
2151 Parser.Lex(); // Eat '#'
2152 else if (Parser.getTok().isNot(AsmToken::Integer))
2153 // Operand should start from # or should be integer, emit error otherwise.
2154 return MatchOperand_NoMatch;
2155
2156 const MCExpr *Imm;
2157 if (parseSymbolicImmVal(Imm))
2158 return MatchOperand_ParseFail;
2159 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2160 uint64_t ShiftAmount = 0;
2161 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2162 if (MCE) {
2163 int64_t Val = MCE->getValue();
2164 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002165 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002166 ShiftAmount = 12;
2167 }
2168 }
2169 SMLoc E = Parser.getTok().getLoc();
2170 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2171 getContext()));
2172 return MatchOperand_Success;
2173 }
2174
2175 // Eat ','
2176 Parser.Lex();
2177
2178 // The optional operand must be "lsl #N" where N is non-negative.
2179 if (!Parser.getTok().is(AsmToken::Identifier) ||
2180 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2181 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2182 return MatchOperand_ParseFail;
2183 }
2184
2185 // Eat 'lsl'
2186 Parser.Lex();
2187
Nirav Davee833c6c2016-11-08 18:31:04 +00002188 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002189
2190 if (Parser.getTok().isNot(AsmToken::Integer)) {
2191 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2192 return MatchOperand_ParseFail;
2193 }
2194
2195 int64_t ShiftAmount = Parser.getTok().getIntVal();
2196
2197 if (ShiftAmount < 0) {
2198 Error(Parser.getTok().getLoc(), "positive shift amount required");
2199 return MatchOperand_ParseFail;
2200 }
2201 Parser.Lex(); // Eat the number
2202
2203 SMLoc E = Parser.getTok().getLoc();
2204 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2205 S, E, getContext()));
2206 return MatchOperand_Success;
2207}
2208
2209/// parseCondCodeString - Parse a Condition Code string.
2210AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2211 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2212 .Case("eq", AArch64CC::EQ)
2213 .Case("ne", AArch64CC::NE)
2214 .Case("cs", AArch64CC::HS)
2215 .Case("hs", AArch64CC::HS)
2216 .Case("cc", AArch64CC::LO)
2217 .Case("lo", AArch64CC::LO)
2218 .Case("mi", AArch64CC::MI)
2219 .Case("pl", AArch64CC::PL)
2220 .Case("vs", AArch64CC::VS)
2221 .Case("vc", AArch64CC::VC)
2222 .Case("hi", AArch64CC::HI)
2223 .Case("ls", AArch64CC::LS)
2224 .Case("ge", AArch64CC::GE)
2225 .Case("lt", AArch64CC::LT)
2226 .Case("gt", AArch64CC::GT)
2227 .Case("le", AArch64CC::LE)
2228 .Case("al", AArch64CC::AL)
2229 .Case("nv", AArch64CC::NV)
2230 .Default(AArch64CC::Invalid);
2231 return CC;
2232}
2233
2234/// parseCondCode - Parse a Condition Code operand.
2235bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2236 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002237 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002238 SMLoc S = getLoc();
2239 const AsmToken &Tok = Parser.getTok();
2240 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2241
2242 StringRef Cond = Tok.getString();
2243 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2244 if (CC == AArch64CC::Invalid)
2245 return TokError("invalid condition code");
2246 Parser.Lex(); // Eat identifier token.
2247
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002248 if (invertCondCode) {
2249 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2250 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002251 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002252 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002253
2254 Operands.push_back(
2255 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2256 return false;
2257}
2258
2259/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2260/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002261OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002262AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002263 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002264 const AsmToken &Tok = Parser.getTok();
2265 std::string LowerID = Tok.getString().lower();
2266 AArch64_AM::ShiftExtendType ShOp =
2267 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2268 .Case("lsl", AArch64_AM::LSL)
2269 .Case("lsr", AArch64_AM::LSR)
2270 .Case("asr", AArch64_AM::ASR)
2271 .Case("ror", AArch64_AM::ROR)
2272 .Case("msl", AArch64_AM::MSL)
2273 .Case("uxtb", AArch64_AM::UXTB)
2274 .Case("uxth", AArch64_AM::UXTH)
2275 .Case("uxtw", AArch64_AM::UXTW)
2276 .Case("uxtx", AArch64_AM::UXTX)
2277 .Case("sxtb", AArch64_AM::SXTB)
2278 .Case("sxth", AArch64_AM::SXTH)
2279 .Case("sxtw", AArch64_AM::SXTW)
2280 .Case("sxtx", AArch64_AM::SXTX)
2281 .Default(AArch64_AM::InvalidShiftExtend);
2282
2283 if (ShOp == AArch64_AM::InvalidShiftExtend)
2284 return MatchOperand_NoMatch;
2285
2286 SMLoc S = Tok.getLoc();
2287 Parser.Lex();
2288
Nirav Davee833c6c2016-11-08 18:31:04 +00002289 bool Hash = parseOptionalToken(AsmToken::Hash);
2290
Tim Northover3b0846e2014-05-24 12:50:23 +00002291 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2292 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2293 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2294 ShOp == AArch64_AM::MSL) {
2295 // We expect a number here.
2296 TokError("expected #imm after shift specifier");
2297 return MatchOperand_ParseFail;
2298 }
2299
Chad Rosier2ff37b82016-12-27 16:58:09 +00002300 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002301 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2302 Operands.push_back(
2303 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2304 return MatchOperand_Success;
2305 }
2306
Chad Rosier2ff37b82016-12-27 16:58:09 +00002307 // Make sure we do actually have a number, identifier or a parenthesized
2308 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002309 SMLoc E = Parser.getTok().getLoc();
2310 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002311 !Parser.getTok().is(AsmToken::LParen) &&
2312 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002313 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002314 return MatchOperand_ParseFail;
2315 }
2316
2317 const MCExpr *ImmVal;
2318 if (getParser().parseExpression(ImmVal))
2319 return MatchOperand_ParseFail;
2320
2321 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2322 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002323 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002324 return MatchOperand_ParseFail;
2325 }
2326
Jim Grosbach57fd2622014-09-23 22:16:02 +00002327 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002328 Operands.push_back(AArch64Operand::CreateShiftExtend(
2329 ShOp, MCE->getValue(), true, S, E, getContext()));
2330 return MatchOperand_Success;
2331}
2332
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002333static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2334 if (FBS[AArch64::HasV8_1aOps])
2335 Str += "ARMv8.1a";
2336 else if (FBS[AArch64::HasV8_2aOps])
2337 Str += "ARMv8.2a";
2338 else
2339 Str += "(unknown)";
2340}
2341
2342void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2343 SMLoc S) {
2344 const uint16_t Op2 = Encoding & 7;
2345 const uint16_t Cm = (Encoding & 0x78) >> 3;
2346 const uint16_t Cn = (Encoding & 0x780) >> 7;
2347 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2348
2349 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2350
2351 Operands.push_back(
2352 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2353 Operands.push_back(
2354 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2355 Operands.push_back(
2356 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2357 Expr = MCConstantExpr::create(Op2, getContext());
2358 Operands.push_back(
2359 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2360}
2361
Tim Northover3b0846e2014-05-24 12:50:23 +00002362/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2363/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2364bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2365 OperandVector &Operands) {
2366 if (Name.find('.') != StringRef::npos)
2367 return TokError("invalid operand");
2368
2369 Mnemonic = Name;
2370 Operands.push_back(
2371 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2372
Rafael Espindola961d4692014-11-11 05:18:41 +00002373 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002374 const AsmToken &Tok = Parser.getTok();
2375 StringRef Op = Tok.getString();
2376 SMLoc S = Tok.getLoc();
2377
Tim Northover3b0846e2014-05-24 12:50:23 +00002378 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002379 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2380 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002381 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002382 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2383 std::string Str("IC " + std::string(IC->Name) + " requires ");
2384 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2385 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002386 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002387 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002388 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002389 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2390 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002391 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002392 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2393 std::string Str("DC " + std::string(DC->Name) + " requires ");
2394 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2395 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002396 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002397 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002398 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002399 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2400 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002401 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002402 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2403 std::string Str("AT " + std::string(AT->Name) + " requires ");
2404 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2405 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002406 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002407 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002408 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002409 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2410 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002411 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002412 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2413 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2414 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2415 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002416 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002417 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002418 }
2419
Tim Northover3b0846e2014-05-24 12:50:23 +00002420 Parser.Lex(); // Eat operand.
2421
2422 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2423 bool HasRegister = false;
2424
2425 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002426 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002427 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2428 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002429 HasRegister = true;
2430 }
2431
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002432 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002433 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002434 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002435 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002436
Nirav Davee833c6c2016-11-08 18:31:04 +00002437 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2438 return true;
2439
Tim Northover3b0846e2014-05-24 12:50:23 +00002440 return false;
2441}
2442
Alex Bradbury58eba092016-11-01 16:32:05 +00002443OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002444AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002445 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002446 const AsmToken &Tok = Parser.getTok();
2447
2448 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002449 if (parseOptionalToken(AsmToken::Hash) ||
2450 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002451 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002452 const MCExpr *ImmVal;
2453 SMLoc ExprLoc = getLoc();
2454 if (getParser().parseExpression(ImmVal))
2455 return MatchOperand_ParseFail;
2456 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2457 if (!MCE) {
2458 Error(ExprLoc, "immediate value expected for barrier operand");
2459 return MatchOperand_ParseFail;
2460 }
2461 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2462 Error(ExprLoc, "barrier operand out of range");
2463 return MatchOperand_ParseFail;
2464 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002465 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2466 Operands.push_back(AArch64Operand::CreateBarrier(
2467 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002468 return MatchOperand_Success;
2469 }
2470
2471 if (Tok.isNot(AsmToken::Identifier)) {
2472 TokError("invalid operand for instruction");
2473 return MatchOperand_ParseFail;
2474 }
2475
Tim Northover3b0846e2014-05-24 12:50:23 +00002476 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002477 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2478 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002479 TokError("'sy' or #imm operand expected");
2480 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002481 } else if (!DB) {
2482 TokError("invalid barrier option name");
2483 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002484 }
2485
Tim Northovere6ae6762016-07-05 21:23:04 +00002486 Operands.push_back(AArch64Operand::CreateBarrier(
2487 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002488 Parser.Lex(); // Consume the option
2489
2490 return MatchOperand_Success;
2491}
2492
Alex Bradbury58eba092016-11-01 16:32:05 +00002493OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002494AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002495 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002496 const AsmToken &Tok = Parser.getTok();
2497
2498 if (Tok.isNot(AsmToken::Identifier))
2499 return MatchOperand_NoMatch;
2500
Tim Northovere6ae6762016-07-05 21:23:04 +00002501 int MRSReg, MSRReg;
2502 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2503 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2504 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2505 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2506 } else
2507 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002508
Tim Northovere6ae6762016-07-05 21:23:04 +00002509 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2510 unsigned PStateImm = -1;
2511 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2512 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002513
Tim Northovere6ae6762016-07-05 21:23:04 +00002514 Operands.push_back(
2515 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2516 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002517 Parser.Lex(); // Eat identifier
2518
2519 return MatchOperand_Success;
2520}
2521
2522/// tryParseVectorRegister - Parse a vector register operand.
2523bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002524 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002525 if (Parser.getTok().isNot(AsmToken::Identifier))
2526 return true;
2527
2528 SMLoc S = getLoc();
2529 // Check for a vector register specifier first.
2530 StringRef Kind;
2531 int64_t Reg = tryMatchVectorRegister(Kind, false);
2532 if (Reg == -1)
2533 return true;
2534 Operands.push_back(
2535 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2536 // If there was an explicit qualifier, that goes on as a literal text
2537 // operand.
2538 if (!Kind.empty())
2539 Operands.push_back(
2540 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2541
2542 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002543 SMLoc SIdx = getLoc();
2544 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002545 const MCExpr *ImmVal;
2546 if (getParser().parseExpression(ImmVal))
2547 return false;
2548 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2549 if (!MCE) {
2550 TokError("immediate value expected for vector index");
2551 return false;
2552 }
2553
2554 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002555
Nirav Davee833c6c2016-11-08 18:31:04 +00002556 if (parseToken(AsmToken::RBrac, "']' expected"))
2557 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002558
2559 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2560 E, getContext()));
2561 }
2562
2563 return false;
2564}
2565
2566/// parseRegister - Parse a non-vector register operand.
2567bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2568 SMLoc S = getLoc();
2569 // Try for a vector register.
2570 if (!tryParseVectorRegister(Operands))
2571 return false;
2572
2573 // Try for a scalar register.
2574 int64_t Reg = tryParseRegister();
2575 if (Reg == -1)
2576 return true;
2577 Operands.push_back(
2578 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2579
Tim Northover3b0846e2014-05-24 12:50:23 +00002580 return false;
2581}
2582
2583bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002584 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002585 bool HasELFModifier = false;
2586 AArch64MCExpr::VariantKind RefKind;
2587
Nirav Davee833c6c2016-11-08 18:31:04 +00002588 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002589 HasELFModifier = true;
2590
Nirav Davee833c6c2016-11-08 18:31:04 +00002591 if (Parser.getTok().isNot(AsmToken::Identifier))
2592 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002593
2594 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2595 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2596 .Case("lo12", AArch64MCExpr::VK_LO12)
2597 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2598 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2599 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2600 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2601 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2602 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2603 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2604 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2605 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2606 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2607 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2608 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2609 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2610 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2611 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2612 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2613 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2614 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2615 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2616 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2617 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2618 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2619 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2620 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2621 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2622 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2623 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2624 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2625 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2626 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2627 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2628 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2629 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2630 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2631 .Default(AArch64MCExpr::VK_INVALID);
2632
Nirav Davee833c6c2016-11-08 18:31:04 +00002633 if (RefKind == AArch64MCExpr::VK_INVALID)
2634 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002635
2636 Parser.Lex(); // Eat identifier
2637
Nirav Davee833c6c2016-11-08 18:31:04 +00002638 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002639 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002640 }
2641
2642 if (getParser().parseExpression(ImmVal))
2643 return true;
2644
2645 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002646 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002647
2648 return false;
2649}
2650
2651/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2652bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002653 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002654 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2655 SMLoc S = getLoc();
2656 Parser.Lex(); // Eat left bracket token.
2657 StringRef Kind;
2658 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2659 if (FirstReg == -1)
2660 return true;
2661 int64_t PrevReg = FirstReg;
2662 unsigned Count = 1;
2663
Nirav Davee833c6c2016-11-08 18:31:04 +00002664 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002665 SMLoc Loc = getLoc();
2666 StringRef NextKind;
2667 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2668 if (Reg == -1)
2669 return true;
2670 // Any Kind suffices must match on all regs in the list.
2671 if (Kind != NextKind)
2672 return Error(Loc, "mismatched register size suffix");
2673
2674 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2675
2676 if (Space == 0 || Space > 3) {
2677 return Error(Loc, "invalid number of vectors");
2678 }
2679
2680 Count += Space;
2681 }
2682 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002683 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002684 SMLoc Loc = getLoc();
2685 StringRef NextKind;
2686 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2687 if (Reg == -1)
2688 return true;
2689 // Any Kind suffices must match on all regs in the list.
2690 if (Kind != NextKind)
2691 return Error(Loc, "mismatched register size suffix");
2692
2693 // Registers must be incremental (with wraparound at 31)
2694 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2695 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2696 return Error(Loc, "registers must be sequential");
2697
2698 PrevReg = Reg;
2699 ++Count;
2700 }
2701 }
2702
Nirav Davee833c6c2016-11-08 18:31:04 +00002703 if (parseToken(AsmToken::RCurly, "'}' expected"))
2704 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002705
2706 if (Count > 4)
2707 return Error(S, "invalid number of vectors");
2708
2709 unsigned NumElements = 0;
2710 char ElementKind = 0;
2711 if (!Kind.empty())
2712 parseValidVectorKind(Kind, NumElements, ElementKind);
2713
2714 Operands.push_back(AArch64Operand::CreateVectorList(
2715 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2716
2717 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002718 SMLoc SIdx = getLoc();
2719 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002720 const MCExpr *ImmVal;
2721 if (getParser().parseExpression(ImmVal))
2722 return false;
2723 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2724 if (!MCE) {
2725 TokError("immediate value expected for vector index");
2726 return false;
2727 }
2728
2729 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002730 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002731 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002732
2733 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2734 E, getContext()));
2735 }
2736 return false;
2737}
2738
Alex Bradbury58eba092016-11-01 16:32:05 +00002739OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002740AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002741 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002742 const AsmToken &Tok = Parser.getTok();
2743 if (!Tok.is(AsmToken::Identifier))
2744 return MatchOperand_NoMatch;
2745
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002746 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00002747
2748 MCContext &Ctx = getContext();
2749 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2750 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2751 return MatchOperand_NoMatch;
2752
2753 SMLoc S = getLoc();
2754 Parser.Lex(); // Eat register
2755
Nirav Davee833c6c2016-11-08 18:31:04 +00002756 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002757 Operands.push_back(
2758 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2759 return MatchOperand_Success;
2760 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002761
Nirav Davee833c6c2016-11-08 18:31:04 +00002762 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002763
2764 if (Parser.getTok().isNot(AsmToken::Integer)) {
2765 Error(getLoc(), "index must be absent or #0");
2766 return MatchOperand_ParseFail;
2767 }
2768
2769 const MCExpr *ImmVal;
2770 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2771 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2772 Error(getLoc(), "index must be absent or #0");
2773 return MatchOperand_ParseFail;
2774 }
2775
2776 Operands.push_back(
2777 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2778 return MatchOperand_Success;
2779}
2780
2781/// parseOperand - Parse a arm instruction operand. For now this parses the
2782/// operand regardless of the mnemonic.
2783bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
2784 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002785 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002786 // Check if the current operand has a custom associated parser, if so, try to
2787 // custom parse the operand, or fallback to the general approach.
2788 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2789 if (ResTy == MatchOperand_Success)
2790 return false;
2791 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2792 // there was a match, but an error occurred, in which case, just return that
2793 // the operand parsing failed.
2794 if (ResTy == MatchOperand_ParseFail)
2795 return true;
2796
2797 // Nothing custom, so do general case parsing.
2798 SMLoc S, E;
2799 switch (getLexer().getKind()) {
2800 default: {
2801 SMLoc S = getLoc();
2802 const MCExpr *Expr;
2803 if (parseSymbolicImmVal(Expr))
2804 return Error(S, "invalid operand");
2805
2806 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2807 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2808 return false;
2809 }
2810 case AsmToken::LBrac: {
2811 SMLoc Loc = Parser.getTok().getLoc();
2812 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
2813 getContext()));
2814 Parser.Lex(); // Eat '['
2815
2816 // There's no comma after a '[', so we can parse the next operand
2817 // immediately.
2818 return parseOperand(Operands, false, false);
2819 }
2820 case AsmToken::LCurly:
2821 return parseVectorList(Operands);
2822 case AsmToken::Identifier: {
2823 // If we're expecting a Condition Code operand, then just parse that.
2824 if (isCondCode)
2825 return parseCondCode(Operands, invertCondCode);
2826
2827 // If it's a register name, parse it.
2828 if (!parseRegister(Operands))
2829 return false;
2830
2831 // This could be an optional "shift" or "extend" operand.
2832 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
2833 // We can only continue if no tokens were eaten.
2834 if (GotShift != MatchOperand_NoMatch)
2835 return GotShift;
2836
2837 // This was not a register so parse other operands that start with an
2838 // identifier (like labels) as expressions and create them as immediates.
2839 const MCExpr *IdVal;
2840 S = getLoc();
2841 if (getParser().parseExpression(IdVal))
2842 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002843 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2844 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
2845 return false;
2846 }
2847 case AsmToken::Integer:
2848 case AsmToken::Real:
2849 case AsmToken::Hash: {
2850 // #42 -> immediate.
2851 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002852
2853 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002854
2855 // Parse a negative sign
2856 bool isNegative = false;
2857 if (Parser.getTok().is(AsmToken::Minus)) {
2858 isNegative = true;
2859 // We need to consume this token only when we have a Real, otherwise
2860 // we let parseSymbolicImmVal take care of it
2861 if (Parser.getLexer().peekTok().is(AsmToken::Real))
2862 Parser.Lex();
2863 }
2864
2865 // The only Real that should come through here is a literal #0.0 for
2866 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
2867 // so convert the value.
2868 const AsmToken &Tok = Parser.getTok();
2869 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002870 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002871 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2872 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
2873 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
2874 Mnemonic != "fcmlt")
2875 return TokError("unexpected floating point literal");
2876 else if (IntVal != 0 || isNegative)
2877 return TokError("expected floating-point constant #0.0");
2878 Parser.Lex(); // Eat the token.
2879
2880 Operands.push_back(
2881 AArch64Operand::CreateToken("#0", false, S, getContext()));
2882 Operands.push_back(
2883 AArch64Operand::CreateToken(".0", false, S, getContext()));
2884 return false;
2885 }
2886
2887 const MCExpr *ImmVal;
2888 if (parseSymbolicImmVal(ImmVal))
2889 return true;
2890
2891 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2892 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
2893 return false;
2894 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002895 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00002896 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002897 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00002898 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002899 Parser.Lex(); // Eat '='
2900 const MCExpr *SubExprVal;
2901 if (getParser().parseExpression(SubExprVal))
2902 return true;
2903
David Peixottoae5ba762014-07-18 16:05:14 +00002904 if (Operands.size() < 2 ||
2905 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00002906 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00002907
2908 bool IsXReg =
2909 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
2910 Operands[1]->getReg());
2911
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002912 MCContext& Ctx = getContext();
2913 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
2914 // 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 +00002915 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002916 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
2917 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
2918 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
2919 ShiftAmt += 16;
2920 Imm >>= 16;
2921 }
2922 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
2923 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
2924 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00002925 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002926 if (ShiftAmt)
2927 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
2928 ShiftAmt, true, S, E, Ctx));
2929 return false;
2930 }
David Peixottoae5ba762014-07-18 16:05:14 +00002931 APInt Simm = APInt(64, Imm << ShiftAmt);
2932 // check if the immediate is an unsigned or signed 32-bit int for W regs
2933 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
2934 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002935 }
2936 // 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 +00002937 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00002938 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002939 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
2940 return false;
2941 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002942 }
2943}
2944
2945/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
2946/// operands.
2947bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
2948 StringRef Name, SMLoc NameLoc,
2949 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002950 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002951 Name = StringSwitch<StringRef>(Name.lower())
2952 .Case("beq", "b.eq")
2953 .Case("bne", "b.ne")
2954 .Case("bhs", "b.hs")
2955 .Case("bcs", "b.cs")
2956 .Case("blo", "b.lo")
2957 .Case("bcc", "b.cc")
2958 .Case("bmi", "b.mi")
2959 .Case("bpl", "b.pl")
2960 .Case("bvs", "b.vs")
2961 .Case("bvc", "b.vc")
2962 .Case("bhi", "b.hi")
2963 .Case("bls", "b.ls")
2964 .Case("bge", "b.ge")
2965 .Case("blt", "b.lt")
2966 .Case("bgt", "b.gt")
2967 .Case("ble", "b.le")
2968 .Case("bal", "b.al")
2969 .Case("bnv", "b.nv")
2970 .Default(Name);
2971
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002972 // First check for the AArch64-specific .req directive.
2973 if (Parser.getTok().is(AsmToken::Identifier) &&
2974 Parser.getTok().getIdentifier() == ".req") {
2975 parseDirectiveReq(Name, NameLoc);
2976 // We always return 'error' for this, as we're done with this
2977 // statement and don't need to match the 'instruction."
2978 return true;
2979 }
2980
Tim Northover3b0846e2014-05-24 12:50:23 +00002981 // Create the leading tokens for the mnemonic, split by '.' characters.
2982 size_t Start = 0, Next = Name.find('.');
2983 StringRef Head = Name.slice(Start, Next);
2984
2985 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00002986 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
2987 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00002988
2989 Operands.push_back(
2990 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
2991 Mnemonic = Head;
2992
2993 // Handle condition codes for a branch mnemonic
2994 if (Head == "b" && Next != StringRef::npos) {
2995 Start = Next;
2996 Next = Name.find('.', Start + 1);
2997 Head = Name.slice(Start + 1, Next);
2998
2999 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3000 (Head.data() - Name.data()));
3001 AArch64CC::CondCode CC = parseCondCodeString(Head);
3002 if (CC == AArch64CC::Invalid)
3003 return Error(SuffixLoc, "invalid condition code");
3004 Operands.push_back(
3005 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3006 Operands.push_back(
3007 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3008 }
3009
3010 // Add the remaining tokens in the mnemonic.
3011 while (Next != StringRef::npos) {
3012 Start = Next;
3013 Next = Name.find('.', Start + 1);
3014 Head = Name.slice(Start, Next);
3015 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3016 (Head.data() - Name.data()) + 1);
3017 Operands.push_back(
3018 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3019 }
3020
3021 // Conditional compare instructions have a Condition Code operand, which needs
3022 // to be parsed and an immediate operand created.
3023 bool condCodeFourthOperand =
3024 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3025 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3026 Head == "csinc" || Head == "csinv" || Head == "csneg");
3027
3028 // These instructions are aliases to some of the conditional select
3029 // instructions. However, the condition code is inverted in the aliased
3030 // instruction.
3031 //
3032 // FIXME: Is this the correct way to handle these? Or should the parser
3033 // generate the aliased instructions directly?
3034 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3035 bool condCodeThirdOperand =
3036 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3037
3038 // Read the remaining operands.
3039 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3040 // Read the first operand.
3041 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003042 return true;
3043 }
3044
3045 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003046 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003047 // Parse and remember the operand.
3048 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3049 (N == 3 && condCodeThirdOperand) ||
3050 (N == 2 && condCodeSecondOperand),
3051 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003052 return true;
3053 }
3054
3055 // After successfully parsing some operands there are two special cases to
3056 // consider (i.e. notional operands not separated by commas). Both are due
3057 // to memory specifiers:
3058 // + An RBrac will end an address for load/store/prefetch
3059 // + An '!' will indicate a pre-indexed operation.
3060 //
3061 // It's someone else's responsibility to make sure these tokens are sane
3062 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003063
Nirav Davee833c6c2016-11-08 18:31:04 +00003064 SMLoc RLoc = Parser.getTok().getLoc();
3065 if (parseOptionalToken(AsmToken::RBrac))
3066 Operands.push_back(
3067 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3068 SMLoc ELoc = Parser.getTok().getLoc();
3069 if (parseOptionalToken(AsmToken::Exclaim))
3070 Operands.push_back(
3071 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003072
3073 ++N;
3074 }
3075 }
3076
Nirav Davee833c6c2016-11-08 18:31:04 +00003077 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3078 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003079
Tim Northover3b0846e2014-05-24 12:50:23 +00003080 return false;
3081}
3082
3083// FIXME: This entire function is a giant hack to provide us with decent
3084// operand range validation/diagnostics until TableGen/MC can be extended
3085// to support autogeneration of this kind of validation.
3086bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3087 SmallVectorImpl<SMLoc> &Loc) {
3088 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3089 // Check for indexed addressing modes w/ the base register being the
3090 // same as a destination/source register or pair load where
3091 // the Rt == Rt2. All of those are undefined behaviour.
3092 switch (Inst.getOpcode()) {
3093 case AArch64::LDPSWpre:
3094 case AArch64::LDPWpost:
3095 case AArch64::LDPWpre:
3096 case AArch64::LDPXpost:
3097 case AArch64::LDPXpre: {
3098 unsigned Rt = Inst.getOperand(1).getReg();
3099 unsigned Rt2 = Inst.getOperand(2).getReg();
3100 unsigned Rn = Inst.getOperand(3).getReg();
3101 if (RI->isSubRegisterEq(Rn, Rt))
3102 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3103 "is also a destination");
3104 if (RI->isSubRegisterEq(Rn, Rt2))
3105 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3106 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003107 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003108 }
3109 case AArch64::LDPDi:
3110 case AArch64::LDPQi:
3111 case AArch64::LDPSi:
3112 case AArch64::LDPSWi:
3113 case AArch64::LDPWi:
3114 case AArch64::LDPXi: {
3115 unsigned Rt = Inst.getOperand(0).getReg();
3116 unsigned Rt2 = Inst.getOperand(1).getReg();
3117 if (Rt == Rt2)
3118 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3119 break;
3120 }
3121 case AArch64::LDPDpost:
3122 case AArch64::LDPDpre:
3123 case AArch64::LDPQpost:
3124 case AArch64::LDPQpre:
3125 case AArch64::LDPSpost:
3126 case AArch64::LDPSpre:
3127 case AArch64::LDPSWpost: {
3128 unsigned Rt = Inst.getOperand(1).getReg();
3129 unsigned Rt2 = Inst.getOperand(2).getReg();
3130 if (Rt == Rt2)
3131 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3132 break;
3133 }
3134 case AArch64::STPDpost:
3135 case AArch64::STPDpre:
3136 case AArch64::STPQpost:
3137 case AArch64::STPQpre:
3138 case AArch64::STPSpost:
3139 case AArch64::STPSpre:
3140 case AArch64::STPWpost:
3141 case AArch64::STPWpre:
3142 case AArch64::STPXpost:
3143 case AArch64::STPXpre: {
3144 unsigned Rt = Inst.getOperand(1).getReg();
3145 unsigned Rt2 = Inst.getOperand(2).getReg();
3146 unsigned Rn = Inst.getOperand(3).getReg();
3147 if (RI->isSubRegisterEq(Rn, Rt))
3148 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3149 "is also a source");
3150 if (RI->isSubRegisterEq(Rn, Rt2))
3151 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3152 "is also a source");
3153 break;
3154 }
3155 case AArch64::LDRBBpre:
3156 case AArch64::LDRBpre:
3157 case AArch64::LDRHHpre:
3158 case AArch64::LDRHpre:
3159 case AArch64::LDRSBWpre:
3160 case AArch64::LDRSBXpre:
3161 case AArch64::LDRSHWpre:
3162 case AArch64::LDRSHXpre:
3163 case AArch64::LDRSWpre:
3164 case AArch64::LDRWpre:
3165 case AArch64::LDRXpre:
3166 case AArch64::LDRBBpost:
3167 case AArch64::LDRBpost:
3168 case AArch64::LDRHHpost:
3169 case AArch64::LDRHpost:
3170 case AArch64::LDRSBWpost:
3171 case AArch64::LDRSBXpost:
3172 case AArch64::LDRSHWpost:
3173 case AArch64::LDRSHXpost:
3174 case AArch64::LDRSWpost:
3175 case AArch64::LDRWpost:
3176 case AArch64::LDRXpost: {
3177 unsigned Rt = Inst.getOperand(1).getReg();
3178 unsigned Rn = Inst.getOperand(2).getReg();
3179 if (RI->isSubRegisterEq(Rn, Rt))
3180 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3181 "is also a source");
3182 break;
3183 }
3184 case AArch64::STRBBpost:
3185 case AArch64::STRBpost:
3186 case AArch64::STRHHpost:
3187 case AArch64::STRHpost:
3188 case AArch64::STRWpost:
3189 case AArch64::STRXpost:
3190 case AArch64::STRBBpre:
3191 case AArch64::STRBpre:
3192 case AArch64::STRHHpre:
3193 case AArch64::STRHpre:
3194 case AArch64::STRWpre:
3195 case AArch64::STRXpre: {
3196 unsigned Rt = Inst.getOperand(1).getReg();
3197 unsigned Rn = Inst.getOperand(2).getReg();
3198 if (RI->isSubRegisterEq(Rn, Rt))
3199 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3200 "is also a source");
3201 break;
3202 }
3203 }
3204
3205 // Now check immediate ranges. Separate from the above as there is overlap
3206 // in the instructions being checked and this keeps the nested conditionals
3207 // to a minimum.
3208 switch (Inst.getOpcode()) {
3209 case AArch64::ADDSWri:
3210 case AArch64::ADDSXri:
3211 case AArch64::ADDWri:
3212 case AArch64::ADDXri:
3213 case AArch64::SUBSWri:
3214 case AArch64::SUBSXri:
3215 case AArch64::SUBWri:
3216 case AArch64::SUBXri: {
3217 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3218 // some slight duplication here.
3219 if (Inst.getOperand(2).isExpr()) {
3220 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3221 AArch64MCExpr::VariantKind ELFRefKind;
3222 MCSymbolRefExpr::VariantKind DarwinRefKind;
3223 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003224 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3225
3226 // Only allow these with ADDXri.
3227 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3228 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3229 Inst.getOpcode() == AArch64::ADDXri)
3230 return false;
3231
3232 // Only allow these with ADDXri/ADDWri
3233 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3234 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3235 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3236 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3237 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3238 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3239 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3240 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3241 (Inst.getOpcode() == AArch64::ADDXri ||
3242 Inst.getOpcode() == AArch64::ADDWri))
3243 return false;
3244
3245 // Don't allow symbol refs in the immediate field otherwise
3246 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3247 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3248 // 'cmp w0, 'borked')
3249 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003250 }
Diana Picusc93518d2016-10-11 09:17:47 +00003251 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003252 }
3253 return false;
3254 }
3255 default:
3256 return false;
3257 }
3258}
3259
3260bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3261 switch (ErrCode) {
3262 case Match_MissingFeature:
3263 return Error(Loc,
3264 "instruction requires a CPU feature not currently enabled");
3265 case Match_InvalidOperand:
3266 return Error(Loc, "invalid operand for instruction");
3267 case Match_InvalidSuffix:
3268 return Error(Loc, "invalid type suffix for instruction");
3269 case Match_InvalidCondCode:
3270 return Error(Loc, "expected AArch64 condition code");
3271 case Match_AddSubRegExtendSmall:
3272 return Error(Loc,
3273 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3274 case Match_AddSubRegExtendLarge:
3275 return Error(Loc,
3276 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3277 case Match_AddSubSecondSource:
3278 return Error(Loc,
3279 "expected compatible register, symbol or integer in range [0, 4095]");
3280 case Match_LogicalSecondSource:
3281 return Error(Loc, "expected compatible register or logical immediate");
3282 case Match_InvalidMovImm32Shift:
3283 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3284 case Match_InvalidMovImm64Shift:
3285 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3286 case Match_AddSubRegShift32:
3287 return Error(Loc,
3288 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3289 case Match_AddSubRegShift64:
3290 return Error(Loc,
3291 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3292 case Match_InvalidFPImm:
3293 return Error(Loc,
3294 "expected compatible register or floating-point constant");
3295 case Match_InvalidMemoryIndexedSImm9:
3296 return Error(Loc, "index must be an integer in range [-256, 255].");
3297 case Match_InvalidMemoryIndexed4SImm7:
3298 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3299 case Match_InvalidMemoryIndexed8SImm7:
3300 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3301 case Match_InvalidMemoryIndexed16SImm7:
3302 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3303 case Match_InvalidMemoryWExtend8:
3304 return Error(Loc,
3305 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3306 case Match_InvalidMemoryWExtend16:
3307 return Error(Loc,
3308 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3309 case Match_InvalidMemoryWExtend32:
3310 return Error(Loc,
3311 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3312 case Match_InvalidMemoryWExtend64:
3313 return Error(Loc,
3314 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3315 case Match_InvalidMemoryWExtend128:
3316 return Error(Loc,
3317 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3318 case Match_InvalidMemoryXExtend8:
3319 return Error(Loc,
3320 "expected 'lsl' or 'sxtx' with optional shift of #0");
3321 case Match_InvalidMemoryXExtend16:
3322 return Error(Loc,
3323 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3324 case Match_InvalidMemoryXExtend32:
3325 return Error(Loc,
3326 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3327 case Match_InvalidMemoryXExtend64:
3328 return Error(Loc,
3329 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3330 case Match_InvalidMemoryXExtend128:
3331 return Error(Loc,
3332 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3333 case Match_InvalidMemoryIndexed1:
3334 return Error(Loc, "index must be an integer in range [0, 4095].");
3335 case Match_InvalidMemoryIndexed2:
3336 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3337 case Match_InvalidMemoryIndexed4:
3338 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3339 case Match_InvalidMemoryIndexed8:
3340 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3341 case Match_InvalidMemoryIndexed16:
3342 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003343 case Match_InvalidImm0_1:
3344 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003345 case Match_InvalidImm0_7:
3346 return Error(Loc, "immediate must be an integer in range [0, 7].");
3347 case Match_InvalidImm0_15:
3348 return Error(Loc, "immediate must be an integer in range [0, 15].");
3349 case Match_InvalidImm0_31:
3350 return Error(Loc, "immediate must be an integer in range [0, 31].");
3351 case Match_InvalidImm0_63:
3352 return Error(Loc, "immediate must be an integer in range [0, 63].");
3353 case Match_InvalidImm0_127:
3354 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003355 case Match_InvalidImm0_255:
3356 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003357 case Match_InvalidImm0_65535:
3358 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3359 case Match_InvalidImm1_8:
3360 return Error(Loc, "immediate must be an integer in range [1, 8].");
3361 case Match_InvalidImm1_16:
3362 return Error(Loc, "immediate must be an integer in range [1, 16].");
3363 case Match_InvalidImm1_32:
3364 return Error(Loc, "immediate must be an integer in range [1, 32].");
3365 case Match_InvalidImm1_64:
3366 return Error(Loc, "immediate must be an integer in range [1, 64].");
3367 case Match_InvalidIndex1:
3368 return Error(Loc, "expected lane specifier '[1]'");
3369 case Match_InvalidIndexB:
3370 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3371 case Match_InvalidIndexH:
3372 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3373 case Match_InvalidIndexS:
3374 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3375 case Match_InvalidIndexD:
3376 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3377 case Match_InvalidLabel:
3378 return Error(Loc, "expected label or encodable integer pc offset");
3379 case Match_MRS:
3380 return Error(Loc, "expected readable system register");
3381 case Match_MSR:
3382 return Error(Loc, "expected writable system register or pstate");
3383 case Match_MnemonicFail:
3384 return Error(Loc, "unrecognized instruction mnemonic");
3385 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003386 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003387 }
3388}
3389
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003390static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003391
3392bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3393 OperandVector &Operands,
3394 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003395 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003396 bool MatchingInlineAsm) {
3397 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003398 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3399 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003400
David Blaikie960ea3f2014-06-08 16:18:35 +00003401 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003402 unsigned NumOperands = Operands.size();
3403
3404 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003405 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3406 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3407 if (Op2.isReg() && Op3.isImm()) {
3408 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003409 if (Op3CE) {
3410 uint64_t Op3Val = Op3CE->getValue();
3411 uint64_t NewOp3Val = 0;
3412 uint64_t NewOp4Val = 0;
3413 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003414 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003415 NewOp3Val = (32 - Op3Val) & 0x1f;
3416 NewOp4Val = 31 - Op3Val;
3417 } else {
3418 NewOp3Val = (64 - Op3Val) & 0x3f;
3419 NewOp4Val = 63 - Op3Val;
3420 }
3421
Jim Grosbach13760bd2015-05-30 01:25:56 +00003422 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3423 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003424
3425 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003426 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003427 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003428 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3429 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3430 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003431 }
3432 }
Tim Northover03b99f62015-04-30 18:28:58 +00003433 } else if (NumOperands == 4 && Tok == "bfc") {
3434 // FIXME: Horrible hack to handle BFC->BFM alias.
3435 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3436 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3437 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3438
3439 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3440 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3441 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3442
3443 if (LSBCE && WidthCE) {
3444 uint64_t LSB = LSBCE->getValue();
3445 uint64_t Width = WidthCE->getValue();
3446
3447 uint64_t RegWidth = 0;
3448 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3449 Op1.getReg()))
3450 RegWidth = 64;
3451 else
3452 RegWidth = 32;
3453
3454 if (LSB >= RegWidth)
3455 return Error(LSBOp.getStartLoc(),
3456 "expected integer in range [0, 31]");
3457 if (Width < 1 || Width > RegWidth)
3458 return Error(WidthOp.getStartLoc(),
3459 "expected integer in range [1, 32]");
3460
3461 uint64_t ImmR = 0;
3462 if (RegWidth == 32)
3463 ImmR = (32 - LSB) & 0x1f;
3464 else
3465 ImmR = (64 - LSB) & 0x3f;
3466
3467 uint64_t ImmS = Width - 1;
3468
3469 if (ImmR != 0 && ImmS >= ImmR)
3470 return Error(WidthOp.getStartLoc(),
3471 "requested insert overflows register");
3472
Jim Grosbach13760bd2015-05-30 01:25:56 +00003473 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3474 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003475 Operands[0] = AArch64Operand::CreateToken(
3476 "bfm", false, Op.getStartLoc(), getContext());
3477 Operands[2] = AArch64Operand::CreateReg(
3478 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3479 SMLoc(), getContext());
3480 Operands[3] = AArch64Operand::CreateImm(
3481 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3482 Operands.emplace_back(
3483 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3484 WidthOp.getEndLoc(), getContext()));
3485 }
3486 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003487 } else if (NumOperands == 5) {
3488 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3489 // UBFIZ -> UBFM aliases.
3490 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003491 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3492 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3493 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003494
David Blaikie960ea3f2014-06-08 16:18:35 +00003495 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3496 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3497 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003498
3499 if (Op3CE && Op4CE) {
3500 uint64_t Op3Val = Op3CE->getValue();
3501 uint64_t Op4Val = Op4CE->getValue();
3502
3503 uint64_t RegWidth = 0;
3504 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003505 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003506 RegWidth = 64;
3507 else
3508 RegWidth = 32;
3509
3510 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003511 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003512 "expected integer in range [0, 31]");
3513 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003514 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003515 "expected integer in range [1, 32]");
3516
3517 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003518 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003519 NewOp3Val = (32 - Op3Val) & 0x1f;
3520 else
3521 NewOp3Val = (64 - Op3Val) & 0x3f;
3522
3523 uint64_t NewOp4Val = Op4Val - 1;
3524
3525 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003526 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003527 "requested insert overflows register");
3528
3529 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003530 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003531 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003532 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003533 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003534 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003535 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003536 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003537 if (Tok == "bfi")
3538 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003539 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003540 else if (Tok == "sbfiz")
3541 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003542 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003543 else if (Tok == "ubfiz")
3544 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003545 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003546 else
3547 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003548 }
3549 }
3550
3551 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3552 // UBFX -> UBFM aliases.
3553 } else if (NumOperands == 5 &&
3554 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003555 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3556 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3557 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003558
David Blaikie960ea3f2014-06-08 16:18:35 +00003559 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3560 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3561 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003562
3563 if (Op3CE && Op4CE) {
3564 uint64_t Op3Val = Op3CE->getValue();
3565 uint64_t Op4Val = Op4CE->getValue();
3566
3567 uint64_t RegWidth = 0;
3568 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003569 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003570 RegWidth = 64;
3571 else
3572 RegWidth = 32;
3573
3574 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003575 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003576 "expected integer in range [0, 31]");
3577 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003578 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003579 "expected integer in range [1, 32]");
3580
3581 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3582
3583 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003584 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003585 "requested extract overflows register");
3586
3587 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003588 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003589 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003590 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003591 if (Tok == "bfxil")
3592 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003593 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003594 else if (Tok == "sbfx")
3595 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003596 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003597 else if (Tok == "ubfx")
3598 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003599 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003600 else
3601 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003602 }
3603 }
3604 }
3605 }
3606 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3607 // InstAlias can't quite handle this since the reg classes aren't
3608 // subclasses.
3609 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3610 // The source register can be Wn here, but the matcher expects a
3611 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003612 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3613 if (Op.isReg()) {
3614 unsigned Reg = getXRegFromWReg(Op.getReg());
3615 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3616 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003617 }
3618 }
3619 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3620 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003621 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3622 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003623 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003624 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003625 // The source register can be Wn here, but the matcher expects a
3626 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003627 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3628 if (Op.isReg()) {
3629 unsigned Reg = getXRegFromWReg(Op.getReg());
3630 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3631 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003632 }
3633 }
3634 }
3635 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3636 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003637 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3638 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003639 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003640 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003641 // The source register can be Wn here, but the matcher expects a
3642 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003643 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3644 if (Op.isReg()) {
3645 unsigned Reg = getWRegFromXReg(Op.getReg());
3646 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3647 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003648 }
3649 }
3650 }
3651
Tim Northover3b0846e2014-05-24 12:50:23 +00003652 MCInst Inst;
3653 // First try to match against the secondary set of tables containing the
3654 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3655 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003656 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003657
3658 // If that fails, try against the alternate table containing long-form NEON:
3659 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003660 if (MatchResult != Match_Success) {
3661 // But first, save the short-form match result: we can use it in case the
3662 // long-form match also fails.
3663 auto ShortFormNEONErrorInfo = ErrorInfo;
3664 auto ShortFormNEONMatchResult = MatchResult;
3665
Tim Northover3b0846e2014-05-24 12:50:23 +00003666 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003667 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003668
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003669 // Now, both matches failed, and the long-form match failed on the mnemonic
3670 // suffix token operand. The short-form match failure is probably more
3671 // relevant: use it instead.
3672 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003673 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003674 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3675 MatchResult = ShortFormNEONMatchResult;
3676 ErrorInfo = ShortFormNEONErrorInfo;
3677 }
3678 }
3679
Tim Northover3b0846e2014-05-24 12:50:23 +00003680 switch (MatchResult) {
3681 case Match_Success: {
3682 // Perform range checking and other semantic validations
3683 SmallVector<SMLoc, 8> OperandLocs;
3684 NumOperands = Operands.size();
3685 for (unsigned i = 1; i < NumOperands; ++i)
3686 OperandLocs.push_back(Operands[i]->getStartLoc());
3687 if (validateInstruction(Inst, OperandLocs))
3688 return true;
3689
3690 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003691 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003692 return false;
3693 }
3694 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003695 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003696 // Special case the error message for the very common case where only
3697 // a single subtarget feature is missing (neon, e.g.).
3698 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003699 uint64_t Mask = 1;
3700 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3701 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003702 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003703 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003704 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003705 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003706 }
3707 return Error(IDLoc, Msg);
3708 }
3709 case Match_MnemonicFail:
3710 return showMatchError(IDLoc, MatchResult);
3711 case Match_InvalidOperand: {
3712 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003713
Tim Northover26bb14e2014-08-18 11:49:42 +00003714 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003715 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003716 return Error(IDLoc, "too few operands for instruction",
3717 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003718
David Blaikie960ea3f2014-06-08 16:18:35 +00003719 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003720 if (ErrorLoc == SMLoc())
3721 ErrorLoc = IDLoc;
3722 }
3723 // If the match failed on a suffix token operand, tweak the diagnostic
3724 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003725 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
3726 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00003727 MatchResult = Match_InvalidSuffix;
3728
3729 return showMatchError(ErrorLoc, MatchResult);
3730 }
3731 case Match_InvalidMemoryIndexed1:
3732 case Match_InvalidMemoryIndexed2:
3733 case Match_InvalidMemoryIndexed4:
3734 case Match_InvalidMemoryIndexed8:
3735 case Match_InvalidMemoryIndexed16:
3736 case Match_InvalidCondCode:
3737 case Match_AddSubRegExtendSmall:
3738 case Match_AddSubRegExtendLarge:
3739 case Match_AddSubSecondSource:
3740 case Match_LogicalSecondSource:
3741 case Match_AddSubRegShift32:
3742 case Match_AddSubRegShift64:
3743 case Match_InvalidMovImm32Shift:
3744 case Match_InvalidMovImm64Shift:
3745 case Match_InvalidFPImm:
3746 case Match_InvalidMemoryWExtend8:
3747 case Match_InvalidMemoryWExtend16:
3748 case Match_InvalidMemoryWExtend32:
3749 case Match_InvalidMemoryWExtend64:
3750 case Match_InvalidMemoryWExtend128:
3751 case Match_InvalidMemoryXExtend8:
3752 case Match_InvalidMemoryXExtend16:
3753 case Match_InvalidMemoryXExtend32:
3754 case Match_InvalidMemoryXExtend64:
3755 case Match_InvalidMemoryXExtend128:
3756 case Match_InvalidMemoryIndexed4SImm7:
3757 case Match_InvalidMemoryIndexed8SImm7:
3758 case Match_InvalidMemoryIndexed16SImm7:
3759 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003760 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003761 case Match_InvalidImm0_7:
3762 case Match_InvalidImm0_15:
3763 case Match_InvalidImm0_31:
3764 case Match_InvalidImm0_63:
3765 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003766 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00003767 case Match_InvalidImm0_65535:
3768 case Match_InvalidImm1_8:
3769 case Match_InvalidImm1_16:
3770 case Match_InvalidImm1_32:
3771 case Match_InvalidImm1_64:
3772 case Match_InvalidIndex1:
3773 case Match_InvalidIndexB:
3774 case Match_InvalidIndexH:
3775 case Match_InvalidIndexS:
3776 case Match_InvalidIndexD:
3777 case Match_InvalidLabel:
3778 case Match_MSR:
3779 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00003780 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003781 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003782 // Any time we get here, there's nothing fancy to do. Just get the
3783 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00003784 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003785 if (ErrorLoc == SMLoc())
3786 ErrorLoc = IDLoc;
3787 return showMatchError(ErrorLoc, MatchResult);
3788 }
3789 }
3790
3791 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003792}
3793
3794/// ParseDirective parses the arm specific directives
3795bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00003796 const MCObjectFileInfo::Environment Format =
3797 getContext().getObjectFileInfo()->getObjectFileType();
3798 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
3799 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00003800
Tim Northover3b0846e2014-05-24 12:50:23 +00003801 StringRef IDVal = DirectiveID.getIdentifier();
3802 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003803 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00003804 parseDirectiveArch(Loc);
3805 else if (IDVal == ".cpu")
3806 parseDirectiveCPU(Loc);
3807 else if (IDVal == ".hword")
3808 parseDirectiveWord(2, Loc);
3809 else if (IDVal == ".word")
3810 parseDirectiveWord(4, Loc);
3811 else if (IDVal == ".xword")
3812 parseDirectiveWord(8, Loc);
3813 else if (IDVal == ".tlsdesccall")
3814 parseDirectiveTLSDescCall(Loc);
3815 else if (IDVal == ".ltorg" || IDVal == ".pool")
3816 parseDirectiveLtorg(Loc);
3817 else if (IDVal == ".unreq")
3818 parseDirectiveUnreq(Loc);
3819 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00003820 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00003821 parseDirectiveInst(Loc);
3822 else
3823 return true;
3824 } else if (IDVal == MCLOHDirectiveName())
3825 parseDirectiveLOH(IDVal, Loc);
3826 else
3827 return true;
3828 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003829}
3830
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003831static const struct {
3832 const char *Name;
3833 const FeatureBitset Features;
3834} ExtensionMap[] = {
3835 { "crc", {AArch64::FeatureCRC} },
3836 { "crypto", {AArch64::FeatureCrypto} },
3837 { "fp", {AArch64::FeatureFPARMv8} },
3838 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003839 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00003840 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003841
3842 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003843 { "pan", {} },
3844 { "lor", {} },
3845 { "rdma", {} },
3846 { "profile", {} },
3847};
3848
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003849/// parseDirectiveArch
3850/// ::= .arch token
3851bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
3852 SMLoc ArchLoc = getLoc();
3853
3854 StringRef Arch, ExtensionString;
3855 std::tie(Arch, ExtensionString) =
3856 getParser().parseStringToEndOfStatement().trim().split('+');
3857
3858 unsigned ID = AArch64::parseArch(Arch);
Nirav Davee833c6c2016-11-08 18:31:04 +00003859 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
3860 return Error(ArchLoc, "unknown arch name");
3861
3862 if (parseToken(AsmToken::EndOfStatement))
3863 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003864
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003865 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00003866 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003867 AArch64::getArchFeatures(ID, AArch64Features);
3868 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
3869 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003870
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003871 MCSubtargetInfo &STI = copySTI();
3872 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
3873 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
3874
3875 SmallVector<StringRef, 4> RequestedExtensions;
3876 if (!ExtensionString.empty())
3877 ExtensionString.split(RequestedExtensions, '+');
3878
3879 FeatureBitset Features = STI.getFeatureBits();
3880 for (auto Name : RequestedExtensions) {
3881 bool EnableFeature = true;
3882
3883 if (Name.startswith_lower("no")) {
3884 EnableFeature = false;
3885 Name = Name.substr(2);
3886 }
3887
3888 for (const auto &Extension : ExtensionMap) {
3889 if (Extension.Name != Name)
3890 continue;
3891
3892 if (Extension.Features.none())
3893 report_fatal_error("unsupported architectural extension: " + Name);
3894
3895 FeatureBitset ToggleFeatures = EnableFeature
3896 ? (~Features & Extension.Features)
3897 : ( Features & Extension.Features);
3898 uint64_t Features =
3899 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
3900 setAvailableFeatures(Features);
3901 break;
3902 }
3903 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003904 return false;
3905}
3906
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003907/// parseDirectiveCPU
3908/// ::= .cpu id
3909bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
3910 SMLoc CPULoc = getLoc();
3911
3912 StringRef CPU, ExtensionString;
3913 std::tie(CPU, ExtensionString) =
3914 getParser().parseStringToEndOfStatement().trim().split('+');
3915
Nirav Davee833c6c2016-11-08 18:31:04 +00003916 if (parseToken(AsmToken::EndOfStatement))
3917 return true;
3918
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003919 SmallVector<StringRef, 4> RequestedExtensions;
3920 if (!ExtensionString.empty())
3921 ExtensionString.split(RequestedExtensions, '+');
3922
3923 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
3924 // once that is tablegen'ed
3925 if (!getSTI().isCPUStringValid(CPU)) {
3926 Error(CPULoc, "unknown CPU name");
3927 return false;
3928 }
3929
3930 MCSubtargetInfo &STI = copySTI();
3931 STI.setDefaultFeatures(CPU, "");
3932
3933 FeatureBitset Features = STI.getFeatureBits();
3934 for (auto Name : RequestedExtensions) {
3935 bool EnableFeature = true;
3936
3937 if (Name.startswith_lower("no")) {
3938 EnableFeature = false;
3939 Name = Name.substr(2);
3940 }
3941
3942 for (const auto &Extension : ExtensionMap) {
3943 if (Extension.Name != Name)
3944 continue;
3945
3946 if (Extension.Features.none())
3947 report_fatal_error("unsupported architectural extension: " + Name);
3948
3949 FeatureBitset ToggleFeatures = EnableFeature
3950 ? (~Features & Extension.Features)
3951 : ( Features & Extension.Features);
3952 uint64_t Features =
3953 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
3954 setAvailableFeatures(Features);
3955
3956 break;
3957 }
3958 }
3959 return false;
3960}
3961
Tim Northover3b0846e2014-05-24 12:50:23 +00003962/// parseDirectiveWord
3963/// ::= .word [ expression (, expression)* ]
3964bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003965 auto parseOp = [&]() -> bool {
3966 const MCExpr *Value;
3967 if (getParser().parseExpression(Value))
3968 return true;
3969 getParser().getStreamer().EmitValue(Value, Size, L);
3970 return false;
3971 };
Tim Northover3b0846e2014-05-24 12:50:23 +00003972
Nirav Davee833c6c2016-11-08 18:31:04 +00003973 if (parseMany(parseOp))
3974 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003975 return false;
3976}
3977
Chad Rosierdcd2a302014-10-22 20:35:57 +00003978/// parseDirectiveInst
3979/// ::= .inst opcode [, ...]
3980bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003981 if (getLexer().is(AsmToken::EndOfStatement))
3982 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00003983
Nirav Davee833c6c2016-11-08 18:31:04 +00003984 auto parseOp = [&]() -> bool {
3985 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00003986 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00003987 if (check(getParser().parseExpression(Expr), L, "expected expression"))
3988 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00003989 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00003990 if (check(!Value, L, "expected constant expression"))
3991 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00003992 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00003993 return false;
3994 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00003995
Nirav Davee833c6c2016-11-08 18:31:04 +00003996 if (parseMany(parseOp))
3997 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00003998 return false;
3999}
4000
Tim Northover3b0846e2014-05-24 12:50:23 +00004001// parseDirectiveTLSDescCall:
4002// ::= .tlsdesccall symbol
4003bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4004 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004005 if (check(getParser().parseIdentifier(Name), L,
4006 "expected symbol after directive") ||
4007 parseToken(AsmToken::EndOfStatement))
4008 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004009
Jim Grosbach6f482002015-05-18 18:43:14 +00004010 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004011 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4012 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004013
4014 MCInst Inst;
4015 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004016 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004017
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004018 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004019 return false;
4020}
4021
4022/// ::= .loh <lohName | lohId> label1, ..., labelN
4023/// The number of arguments depends on the loh identifier.
4024bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004025 MCLOHType Kind;
4026 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4027 if (getParser().getTok().isNot(AsmToken::Integer))
4028 return TokError("expected an identifier or a number in directive");
4029 // We successfully get a numeric value for the identifier.
4030 // Check if it is valid.
4031 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004032 if (Id <= -1U && !isValidMCLOHType(Id))
4033 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004034 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004035 } else {
4036 StringRef Name = getTok().getIdentifier();
4037 // We successfully parse an identifier.
4038 // Check if it is a recognized one.
4039 int Id = MCLOHNameToId(Name);
4040
4041 if (Id == -1)
4042 return TokError("invalid identifier in directive");
4043 Kind = (MCLOHType)Id;
4044 }
4045 // Consume the identifier.
4046 Lex();
4047 // Get the number of arguments of this LOH.
4048 int NbArgs = MCLOHIdToNbArgs(Kind);
4049
4050 assert(NbArgs != -1 && "Invalid number of arguments");
4051
4052 SmallVector<MCSymbol *, 3> Args;
4053 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4054 StringRef Name;
4055 if (getParser().parseIdentifier(Name))
4056 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004057 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004058
4059 if (Idx + 1 == NbArgs)
4060 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004061 if (parseToken(AsmToken::Comma,
4062 "unexpected token in '" + Twine(IDVal) + "' directive"))
4063 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004064 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004065 if (parseToken(AsmToken::EndOfStatement,
4066 "unexpected token in '" + Twine(IDVal) + "' directive"))
4067 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004068
4069 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4070 return false;
4071}
4072
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004073/// parseDirectiveLtorg
4074/// ::= .ltorg | .pool
4075bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004076 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4077 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004078 getTargetStreamer().emitCurrentConstantPool();
4079 return false;
4080}
4081
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004082/// parseDirectiveReq
4083/// ::= name .req registername
4084bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004085 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004086 Parser.Lex(); // Eat the '.req' token.
4087 SMLoc SRegLoc = getLoc();
4088 unsigned RegNum = tryParseRegister();
4089 bool IsVector = false;
4090
4091 if (RegNum == static_cast<unsigned>(-1)) {
4092 StringRef Kind;
4093 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004094 if (!Kind.empty())
4095 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004096 IsVector = true;
4097 }
4098
Nirav Dave2364748a2016-09-16 18:30:20 +00004099 if (RegNum == static_cast<unsigned>(-1))
4100 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004101
4102 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004103 if (parseToken(AsmToken::EndOfStatement,
4104 "unexpected input in .req directive"))
4105 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004106
4107 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004108 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004109 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4110
Nirav Dave2364748a2016-09-16 18:30:20 +00004111 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004112}
4113
4114/// parseDirectiveUneq
4115/// ::= .unreq registername
4116bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004117 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004118 if (getTok().isNot(AsmToken::Identifier))
4119 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004120 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4121 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004122 if (parseToken(AsmToken::EndOfStatement))
4123 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004124 return false;
4125}
4126
Tim Northover3b0846e2014-05-24 12:50:23 +00004127bool
4128AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4129 AArch64MCExpr::VariantKind &ELFRefKind,
4130 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4131 int64_t &Addend) {
4132 ELFRefKind = AArch64MCExpr::VK_INVALID;
4133 DarwinRefKind = MCSymbolRefExpr::VK_None;
4134 Addend = 0;
4135
4136 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4137 ELFRefKind = AE->getKind();
4138 Expr = AE->getSubExpr();
4139 }
4140
4141 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4142 if (SE) {
4143 // It's a simple symbol reference with no addend.
4144 DarwinRefKind = SE->getKind();
4145 return true;
4146 }
4147
4148 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4149 if (!BE)
4150 return false;
4151
4152 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4153 if (!SE)
4154 return false;
4155 DarwinRefKind = SE->getKind();
4156
4157 if (BE->getOpcode() != MCBinaryExpr::Add &&
4158 BE->getOpcode() != MCBinaryExpr::Sub)
4159 return false;
4160
4161 // See if the addend is is a constant, otherwise there's more going
4162 // on here than we can deal with.
4163 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4164 if (!AddendExpr)
4165 return false;
4166
4167 Addend = AddendExpr->getValue();
4168 if (BE->getOpcode() == MCBinaryExpr::Sub)
4169 Addend = -Addend;
4170
4171 // It's some symbol reference + a constant addend, but really
4172 // shouldn't use both Darwin and ELF syntax.
4173 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4174 DarwinRefKind == MCSymbolRefExpr::VK_None;
4175}
4176
4177/// Force static initialization.
4178extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004179 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4180 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4181 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004182}
4183
4184#define GET_REGISTER_MATCHER
4185#define GET_SUBTARGET_FEATURE_NAME
4186#define GET_MATCHER_IMPLEMENTATION
4187#include "AArch64GenAsmMatcher.inc"
4188
4189// Define this matcher function after the auto-generated include so we
4190// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004191unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004192 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004193 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004194 // If the kind is a token for a literal immediate, check if our asm
4195 // operand matches. This is for InstAliases which have a fixed-value
4196 // immediate in the syntax.
4197 int64_t ExpectedVal;
4198 switch (Kind) {
4199 default:
4200 return Match_InvalidOperand;
4201 case MCK__35_0:
4202 ExpectedVal = 0;
4203 break;
4204 case MCK__35_1:
4205 ExpectedVal = 1;
4206 break;
4207 case MCK__35_12:
4208 ExpectedVal = 12;
4209 break;
4210 case MCK__35_16:
4211 ExpectedVal = 16;
4212 break;
4213 case MCK__35_2:
4214 ExpectedVal = 2;
4215 break;
4216 case MCK__35_24:
4217 ExpectedVal = 24;
4218 break;
4219 case MCK__35_3:
4220 ExpectedVal = 3;
4221 break;
4222 case MCK__35_32:
4223 ExpectedVal = 32;
4224 break;
4225 case MCK__35_4:
4226 ExpectedVal = 4;
4227 break;
4228 case MCK__35_48:
4229 ExpectedVal = 48;
4230 break;
4231 case MCK__35_6:
4232 ExpectedVal = 6;
4233 break;
4234 case MCK__35_64:
4235 ExpectedVal = 64;
4236 break;
4237 case MCK__35_8:
4238 ExpectedVal = 8;
4239 break;
4240 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004241 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004242 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004243 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004244 if (!CE)
4245 return Match_InvalidOperand;
4246 if (CE->getValue() == ExpectedVal)
4247 return Match_Success;
4248 return Match_InvalidOperand;
4249}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004250
Alex Bradbury58eba092016-11-01 16:32:05 +00004251OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004252AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4253
4254 SMLoc S = getLoc();
4255
4256 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4257 Error(S, "expected register");
4258 return MatchOperand_ParseFail;
4259 }
4260
4261 int FirstReg = tryParseRegister();
4262 if (FirstReg == -1) {
4263 return MatchOperand_ParseFail;
4264 }
4265 const MCRegisterClass &WRegClass =
4266 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4267 const MCRegisterClass &XRegClass =
4268 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4269
4270 bool isXReg = XRegClass.contains(FirstReg),
4271 isWReg = WRegClass.contains(FirstReg);
4272 if (!isXReg && !isWReg) {
4273 Error(S, "expected first even register of a "
4274 "consecutive same-size even/odd register pair");
4275 return MatchOperand_ParseFail;
4276 }
4277
4278 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4279 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4280
4281 if (FirstEncoding & 0x1) {
4282 Error(S, "expected first even register of a "
4283 "consecutive same-size even/odd register pair");
4284 return MatchOperand_ParseFail;
4285 }
4286
4287 SMLoc M = getLoc();
4288 if (getParser().getTok().isNot(AsmToken::Comma)) {
4289 Error(M, "expected comma");
4290 return MatchOperand_ParseFail;
4291 }
4292 // Eat the comma
4293 getParser().Lex();
4294
4295 SMLoc E = getLoc();
4296 int SecondReg = tryParseRegister();
4297 if (SecondReg ==-1) {
4298 return MatchOperand_ParseFail;
4299 }
4300
Eugene Zelenko049b0172017-01-06 00:30:53 +00004301 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004302 (isXReg && !XRegClass.contains(SecondReg)) ||
4303 (isWReg && !WRegClass.contains(SecondReg))) {
4304 Error(E,"expected second odd register of a "
4305 "consecutive same-size even/odd register pair");
4306 return MatchOperand_ParseFail;
4307 }
Joel Jones504bf332016-10-24 13:37:13 +00004308
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004309 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004310 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004311 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4312 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4313 } else {
4314 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4315 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4316 }
4317
4318 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4319 getContext()));
4320
4321 return MatchOperand_Success;
4322}