blob: 347cffe72c35ee3dbd6e23147d92cede45787b2d [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
2119 // Check for out of range values. As an exception, we let Zero through,
2120 // as we handle that special case in post-processing before matching in
2121 // order to use the zero register for it.
2122 if (Val == -1 && !RealVal.isPosZero()) {
2123 TokError("expected compatible register or floating-point constant");
2124 return MatchOperand_ParseFail;
2125 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002126 }
2127 Parser.Lex(); // Eat the token.
2128 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2129 return MatchOperand_Success;
2130 }
2131
2132 if (!Hash)
2133 return MatchOperand_NoMatch;
2134
2135 TokError("invalid floating point immediate");
2136 return MatchOperand_ParseFail;
2137}
2138
2139/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002140OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002141AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002142 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002143 SMLoc S = getLoc();
2144
2145 if (Parser.getTok().is(AsmToken::Hash))
2146 Parser.Lex(); // Eat '#'
2147 else if (Parser.getTok().isNot(AsmToken::Integer))
2148 // Operand should start from # or should be integer, emit error otherwise.
2149 return MatchOperand_NoMatch;
2150
2151 const MCExpr *Imm;
2152 if (parseSymbolicImmVal(Imm))
2153 return MatchOperand_ParseFail;
2154 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2155 uint64_t ShiftAmount = 0;
2156 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2157 if (MCE) {
2158 int64_t Val = MCE->getValue();
2159 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002160 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002161 ShiftAmount = 12;
2162 }
2163 }
2164 SMLoc E = Parser.getTok().getLoc();
2165 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2166 getContext()));
2167 return MatchOperand_Success;
2168 }
2169
2170 // Eat ','
2171 Parser.Lex();
2172
2173 // The optional operand must be "lsl #N" where N is non-negative.
2174 if (!Parser.getTok().is(AsmToken::Identifier) ||
2175 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2176 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2177 return MatchOperand_ParseFail;
2178 }
2179
2180 // Eat 'lsl'
2181 Parser.Lex();
2182
Nirav Davee833c6c2016-11-08 18:31:04 +00002183 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002184
2185 if (Parser.getTok().isNot(AsmToken::Integer)) {
2186 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2187 return MatchOperand_ParseFail;
2188 }
2189
2190 int64_t ShiftAmount = Parser.getTok().getIntVal();
2191
2192 if (ShiftAmount < 0) {
2193 Error(Parser.getTok().getLoc(), "positive shift amount required");
2194 return MatchOperand_ParseFail;
2195 }
2196 Parser.Lex(); // Eat the number
2197
2198 SMLoc E = Parser.getTok().getLoc();
2199 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2200 S, E, getContext()));
2201 return MatchOperand_Success;
2202}
2203
2204/// parseCondCodeString - Parse a Condition Code string.
2205AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2206 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2207 .Case("eq", AArch64CC::EQ)
2208 .Case("ne", AArch64CC::NE)
2209 .Case("cs", AArch64CC::HS)
2210 .Case("hs", AArch64CC::HS)
2211 .Case("cc", AArch64CC::LO)
2212 .Case("lo", AArch64CC::LO)
2213 .Case("mi", AArch64CC::MI)
2214 .Case("pl", AArch64CC::PL)
2215 .Case("vs", AArch64CC::VS)
2216 .Case("vc", AArch64CC::VC)
2217 .Case("hi", AArch64CC::HI)
2218 .Case("ls", AArch64CC::LS)
2219 .Case("ge", AArch64CC::GE)
2220 .Case("lt", AArch64CC::LT)
2221 .Case("gt", AArch64CC::GT)
2222 .Case("le", AArch64CC::LE)
2223 .Case("al", AArch64CC::AL)
2224 .Case("nv", AArch64CC::NV)
2225 .Default(AArch64CC::Invalid);
2226 return CC;
2227}
2228
2229/// parseCondCode - Parse a Condition Code operand.
2230bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2231 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002232 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002233 SMLoc S = getLoc();
2234 const AsmToken &Tok = Parser.getTok();
2235 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2236
2237 StringRef Cond = Tok.getString();
2238 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2239 if (CC == AArch64CC::Invalid)
2240 return TokError("invalid condition code");
2241 Parser.Lex(); // Eat identifier token.
2242
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002243 if (invertCondCode) {
2244 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2245 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002246 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002247 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002248
2249 Operands.push_back(
2250 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2251 return false;
2252}
2253
2254/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2255/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002256OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002257AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002258 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002259 const AsmToken &Tok = Parser.getTok();
2260 std::string LowerID = Tok.getString().lower();
2261 AArch64_AM::ShiftExtendType ShOp =
2262 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2263 .Case("lsl", AArch64_AM::LSL)
2264 .Case("lsr", AArch64_AM::LSR)
2265 .Case("asr", AArch64_AM::ASR)
2266 .Case("ror", AArch64_AM::ROR)
2267 .Case("msl", AArch64_AM::MSL)
2268 .Case("uxtb", AArch64_AM::UXTB)
2269 .Case("uxth", AArch64_AM::UXTH)
2270 .Case("uxtw", AArch64_AM::UXTW)
2271 .Case("uxtx", AArch64_AM::UXTX)
2272 .Case("sxtb", AArch64_AM::SXTB)
2273 .Case("sxth", AArch64_AM::SXTH)
2274 .Case("sxtw", AArch64_AM::SXTW)
2275 .Case("sxtx", AArch64_AM::SXTX)
2276 .Default(AArch64_AM::InvalidShiftExtend);
2277
2278 if (ShOp == AArch64_AM::InvalidShiftExtend)
2279 return MatchOperand_NoMatch;
2280
2281 SMLoc S = Tok.getLoc();
2282 Parser.Lex();
2283
Nirav Davee833c6c2016-11-08 18:31:04 +00002284 bool Hash = parseOptionalToken(AsmToken::Hash);
2285
Tim Northover3b0846e2014-05-24 12:50:23 +00002286 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2287 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2288 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2289 ShOp == AArch64_AM::MSL) {
2290 // We expect a number here.
2291 TokError("expected #imm after shift specifier");
2292 return MatchOperand_ParseFail;
2293 }
2294
Chad Rosier2ff37b82016-12-27 16:58:09 +00002295 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002296 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2297 Operands.push_back(
2298 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2299 return MatchOperand_Success;
2300 }
2301
Chad Rosier2ff37b82016-12-27 16:58:09 +00002302 // Make sure we do actually have a number, identifier or a parenthesized
2303 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002304 SMLoc E = Parser.getTok().getLoc();
2305 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002306 !Parser.getTok().is(AsmToken::LParen) &&
2307 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002308 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002309 return MatchOperand_ParseFail;
2310 }
2311
2312 const MCExpr *ImmVal;
2313 if (getParser().parseExpression(ImmVal))
2314 return MatchOperand_ParseFail;
2315
2316 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2317 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002318 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002319 return MatchOperand_ParseFail;
2320 }
2321
Jim Grosbach57fd2622014-09-23 22:16:02 +00002322 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002323 Operands.push_back(AArch64Operand::CreateShiftExtend(
2324 ShOp, MCE->getValue(), true, S, E, getContext()));
2325 return MatchOperand_Success;
2326}
2327
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002328static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2329 if (FBS[AArch64::HasV8_1aOps])
2330 Str += "ARMv8.1a";
2331 else if (FBS[AArch64::HasV8_2aOps])
2332 Str += "ARMv8.2a";
2333 else
2334 Str += "(unknown)";
2335}
2336
2337void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2338 SMLoc S) {
2339 const uint16_t Op2 = Encoding & 7;
2340 const uint16_t Cm = (Encoding & 0x78) >> 3;
2341 const uint16_t Cn = (Encoding & 0x780) >> 7;
2342 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2343
2344 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2345
2346 Operands.push_back(
2347 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2348 Operands.push_back(
2349 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2350 Operands.push_back(
2351 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2352 Expr = MCConstantExpr::create(Op2, getContext());
2353 Operands.push_back(
2354 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2355}
2356
Tim Northover3b0846e2014-05-24 12:50:23 +00002357/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2358/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2359bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2360 OperandVector &Operands) {
2361 if (Name.find('.') != StringRef::npos)
2362 return TokError("invalid operand");
2363
2364 Mnemonic = Name;
2365 Operands.push_back(
2366 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2367
Rafael Espindola961d4692014-11-11 05:18:41 +00002368 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002369 const AsmToken &Tok = Parser.getTok();
2370 StringRef Op = Tok.getString();
2371 SMLoc S = Tok.getLoc();
2372
Tim Northover3b0846e2014-05-24 12:50:23 +00002373 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002374 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2375 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002376 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002377 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2378 std::string Str("IC " + std::string(IC->Name) + " requires ");
2379 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2380 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002381 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002382 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002383 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002384 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2385 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002386 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002387 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2388 std::string Str("DC " + std::string(DC->Name) + " requires ");
2389 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2390 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002391 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002392 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002393 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002394 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2395 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002396 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002397 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2398 std::string Str("AT " + std::string(AT->Name) + " requires ");
2399 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2400 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002401 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002402 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002403 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002404 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2405 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002406 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002407 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2408 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2409 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2410 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002411 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002412 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002413 }
2414
Tim Northover3b0846e2014-05-24 12:50:23 +00002415 Parser.Lex(); // Eat operand.
2416
2417 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2418 bool HasRegister = false;
2419
2420 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002421 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002422 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2423 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002424 HasRegister = true;
2425 }
2426
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002427 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002428 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002429 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002430 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002431
Nirav Davee833c6c2016-11-08 18:31:04 +00002432 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2433 return true;
2434
Tim Northover3b0846e2014-05-24 12:50:23 +00002435 return false;
2436}
2437
Alex Bradbury58eba092016-11-01 16:32:05 +00002438OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002439AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002440 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002441 const AsmToken &Tok = Parser.getTok();
2442
2443 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002444 if (parseOptionalToken(AsmToken::Hash) ||
2445 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002446 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002447 const MCExpr *ImmVal;
2448 SMLoc ExprLoc = getLoc();
2449 if (getParser().parseExpression(ImmVal))
2450 return MatchOperand_ParseFail;
2451 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2452 if (!MCE) {
2453 Error(ExprLoc, "immediate value expected for barrier operand");
2454 return MatchOperand_ParseFail;
2455 }
2456 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2457 Error(ExprLoc, "barrier operand out of range");
2458 return MatchOperand_ParseFail;
2459 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002460 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2461 Operands.push_back(AArch64Operand::CreateBarrier(
2462 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002463 return MatchOperand_Success;
2464 }
2465
2466 if (Tok.isNot(AsmToken::Identifier)) {
2467 TokError("invalid operand for instruction");
2468 return MatchOperand_ParseFail;
2469 }
2470
Tim Northovere6ae6762016-07-05 21:23:04 +00002471 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2472 if (!DB) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002473 TokError("invalid barrier option name");
2474 return MatchOperand_ParseFail;
2475 }
2476
2477 // The only valid named option for ISB is 'sy'
Tim Northovere6ae6762016-07-05 21:23:04 +00002478 if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002479 TokError("'sy' or #imm operand expected");
2480 return MatchOperand_ParseFail;
2481 }
2482
Tim Northovere6ae6762016-07-05 21:23:04 +00002483 Operands.push_back(AArch64Operand::CreateBarrier(
2484 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002485 Parser.Lex(); // Consume the option
2486
2487 return MatchOperand_Success;
2488}
2489
Alex Bradbury58eba092016-11-01 16:32:05 +00002490OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002491AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002492 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002493 const AsmToken &Tok = Parser.getTok();
2494
2495 if (Tok.isNot(AsmToken::Identifier))
2496 return MatchOperand_NoMatch;
2497
Tim Northovere6ae6762016-07-05 21:23:04 +00002498 int MRSReg, MSRReg;
2499 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2500 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2501 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2502 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2503 } else
2504 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002505
Tim Northovere6ae6762016-07-05 21:23:04 +00002506 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2507 unsigned PStateImm = -1;
2508 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2509 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002510
Tim Northovere6ae6762016-07-05 21:23:04 +00002511 Operands.push_back(
2512 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2513 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002514 Parser.Lex(); // Eat identifier
2515
2516 return MatchOperand_Success;
2517}
2518
2519/// tryParseVectorRegister - Parse a vector register operand.
2520bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002521 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002522 if (Parser.getTok().isNot(AsmToken::Identifier))
2523 return true;
2524
2525 SMLoc S = getLoc();
2526 // Check for a vector register specifier first.
2527 StringRef Kind;
2528 int64_t Reg = tryMatchVectorRegister(Kind, false);
2529 if (Reg == -1)
2530 return true;
2531 Operands.push_back(
2532 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2533 // If there was an explicit qualifier, that goes on as a literal text
2534 // operand.
2535 if (!Kind.empty())
2536 Operands.push_back(
2537 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2538
2539 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002540 SMLoc SIdx = getLoc();
2541 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002542 const MCExpr *ImmVal;
2543 if (getParser().parseExpression(ImmVal))
2544 return false;
2545 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2546 if (!MCE) {
2547 TokError("immediate value expected for vector index");
2548 return false;
2549 }
2550
2551 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002552
Nirav Davee833c6c2016-11-08 18:31:04 +00002553 if (parseToken(AsmToken::RBrac, "']' expected"))
2554 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002555
2556 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2557 E, getContext()));
2558 }
2559
2560 return false;
2561}
2562
2563/// parseRegister - Parse a non-vector register operand.
2564bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2565 SMLoc S = getLoc();
2566 // Try for a vector register.
2567 if (!tryParseVectorRegister(Operands))
2568 return false;
2569
2570 // Try for a scalar register.
2571 int64_t Reg = tryParseRegister();
2572 if (Reg == -1)
2573 return true;
2574 Operands.push_back(
2575 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2576
Tim Northover3b0846e2014-05-24 12:50:23 +00002577 return false;
2578}
2579
2580bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002581 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002582 bool HasELFModifier = false;
2583 AArch64MCExpr::VariantKind RefKind;
2584
Nirav Davee833c6c2016-11-08 18:31:04 +00002585 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 HasELFModifier = true;
2587
Nirav Davee833c6c2016-11-08 18:31:04 +00002588 if (Parser.getTok().isNot(AsmToken::Identifier))
2589 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002590
2591 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2592 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2593 .Case("lo12", AArch64MCExpr::VK_LO12)
2594 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2595 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2596 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2597 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2598 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2599 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2600 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2601 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2602 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2603 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2604 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2605 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2606 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2607 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2608 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2609 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2610 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2611 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2612 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2613 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2614 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2615 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2616 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2617 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2618 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2619 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2620 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2621 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2622 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2623 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2624 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2625 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2626 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2627 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2628 .Default(AArch64MCExpr::VK_INVALID);
2629
Nirav Davee833c6c2016-11-08 18:31:04 +00002630 if (RefKind == AArch64MCExpr::VK_INVALID)
2631 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002632
2633 Parser.Lex(); // Eat identifier
2634
Nirav Davee833c6c2016-11-08 18:31:04 +00002635 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002636 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002637 }
2638
2639 if (getParser().parseExpression(ImmVal))
2640 return true;
2641
2642 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002643 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002644
2645 return false;
2646}
2647
2648/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2649bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002650 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002651 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2652 SMLoc S = getLoc();
2653 Parser.Lex(); // Eat left bracket token.
2654 StringRef Kind;
2655 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2656 if (FirstReg == -1)
2657 return true;
2658 int64_t PrevReg = FirstReg;
2659 unsigned Count = 1;
2660
Nirav Davee833c6c2016-11-08 18:31:04 +00002661 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002662 SMLoc Loc = getLoc();
2663 StringRef NextKind;
2664 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2665 if (Reg == -1)
2666 return true;
2667 // Any Kind suffices must match on all regs in the list.
2668 if (Kind != NextKind)
2669 return Error(Loc, "mismatched register size suffix");
2670
2671 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2672
2673 if (Space == 0 || Space > 3) {
2674 return Error(Loc, "invalid number of vectors");
2675 }
2676
2677 Count += Space;
2678 }
2679 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002680 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002681 SMLoc Loc = getLoc();
2682 StringRef NextKind;
2683 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2684 if (Reg == -1)
2685 return true;
2686 // Any Kind suffices must match on all regs in the list.
2687 if (Kind != NextKind)
2688 return Error(Loc, "mismatched register size suffix");
2689
2690 // Registers must be incremental (with wraparound at 31)
2691 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2692 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2693 return Error(Loc, "registers must be sequential");
2694
2695 PrevReg = Reg;
2696 ++Count;
2697 }
2698 }
2699
Nirav Davee833c6c2016-11-08 18:31:04 +00002700 if (parseToken(AsmToken::RCurly, "'}' expected"))
2701 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002702
2703 if (Count > 4)
2704 return Error(S, "invalid number of vectors");
2705
2706 unsigned NumElements = 0;
2707 char ElementKind = 0;
2708 if (!Kind.empty())
2709 parseValidVectorKind(Kind, NumElements, ElementKind);
2710
2711 Operands.push_back(AArch64Operand::CreateVectorList(
2712 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2713
2714 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002715 SMLoc SIdx = getLoc();
2716 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002717 const MCExpr *ImmVal;
2718 if (getParser().parseExpression(ImmVal))
2719 return false;
2720 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2721 if (!MCE) {
2722 TokError("immediate value expected for vector index");
2723 return false;
2724 }
2725
2726 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002727 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002728 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002729
2730 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2731 E, getContext()));
2732 }
2733 return false;
2734}
2735
Alex Bradbury58eba092016-11-01 16:32:05 +00002736OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002737AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002738 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002739 const AsmToken &Tok = Parser.getTok();
2740 if (!Tok.is(AsmToken::Identifier))
2741 return MatchOperand_NoMatch;
2742
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002743 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00002744
2745 MCContext &Ctx = getContext();
2746 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2747 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2748 return MatchOperand_NoMatch;
2749
2750 SMLoc S = getLoc();
2751 Parser.Lex(); // Eat register
2752
Nirav Davee833c6c2016-11-08 18:31:04 +00002753 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002754 Operands.push_back(
2755 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2756 return MatchOperand_Success;
2757 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002758
Nirav Davee833c6c2016-11-08 18:31:04 +00002759 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002760
2761 if (Parser.getTok().isNot(AsmToken::Integer)) {
2762 Error(getLoc(), "index must be absent or #0");
2763 return MatchOperand_ParseFail;
2764 }
2765
2766 const MCExpr *ImmVal;
2767 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2768 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2769 Error(getLoc(), "index must be absent or #0");
2770 return MatchOperand_ParseFail;
2771 }
2772
2773 Operands.push_back(
2774 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2775 return MatchOperand_Success;
2776}
2777
2778/// parseOperand - Parse a arm instruction operand. For now this parses the
2779/// operand regardless of the mnemonic.
2780bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
2781 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002782 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002783 // Check if the current operand has a custom associated parser, if so, try to
2784 // custom parse the operand, or fallback to the general approach.
2785 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2786 if (ResTy == MatchOperand_Success)
2787 return false;
2788 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2789 // there was a match, but an error occurred, in which case, just return that
2790 // the operand parsing failed.
2791 if (ResTy == MatchOperand_ParseFail)
2792 return true;
2793
2794 // Nothing custom, so do general case parsing.
2795 SMLoc S, E;
2796 switch (getLexer().getKind()) {
2797 default: {
2798 SMLoc S = getLoc();
2799 const MCExpr *Expr;
2800 if (parseSymbolicImmVal(Expr))
2801 return Error(S, "invalid operand");
2802
2803 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2804 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2805 return false;
2806 }
2807 case AsmToken::LBrac: {
2808 SMLoc Loc = Parser.getTok().getLoc();
2809 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
2810 getContext()));
2811 Parser.Lex(); // Eat '['
2812
2813 // There's no comma after a '[', so we can parse the next operand
2814 // immediately.
2815 return parseOperand(Operands, false, false);
2816 }
2817 case AsmToken::LCurly:
2818 return parseVectorList(Operands);
2819 case AsmToken::Identifier: {
2820 // If we're expecting a Condition Code operand, then just parse that.
2821 if (isCondCode)
2822 return parseCondCode(Operands, invertCondCode);
2823
2824 // If it's a register name, parse it.
2825 if (!parseRegister(Operands))
2826 return false;
2827
2828 // This could be an optional "shift" or "extend" operand.
2829 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
2830 // We can only continue if no tokens were eaten.
2831 if (GotShift != MatchOperand_NoMatch)
2832 return GotShift;
2833
2834 // This was not a register so parse other operands that start with an
2835 // identifier (like labels) as expressions and create them as immediates.
2836 const MCExpr *IdVal;
2837 S = getLoc();
2838 if (getParser().parseExpression(IdVal))
2839 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002840 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2841 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
2842 return false;
2843 }
2844 case AsmToken::Integer:
2845 case AsmToken::Real:
2846 case AsmToken::Hash: {
2847 // #42 -> immediate.
2848 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002849
2850 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002851
2852 // Parse a negative sign
2853 bool isNegative = false;
2854 if (Parser.getTok().is(AsmToken::Minus)) {
2855 isNegative = true;
2856 // We need to consume this token only when we have a Real, otherwise
2857 // we let parseSymbolicImmVal take care of it
2858 if (Parser.getLexer().peekTok().is(AsmToken::Real))
2859 Parser.Lex();
2860 }
2861
2862 // The only Real that should come through here is a literal #0.0 for
2863 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
2864 // so convert the value.
2865 const AsmToken &Tok = Parser.getTok();
2866 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002867 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002868 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2869 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
2870 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
2871 Mnemonic != "fcmlt")
2872 return TokError("unexpected floating point literal");
2873 else if (IntVal != 0 || isNegative)
2874 return TokError("expected floating-point constant #0.0");
2875 Parser.Lex(); // Eat the token.
2876
2877 Operands.push_back(
2878 AArch64Operand::CreateToken("#0", false, S, getContext()));
2879 Operands.push_back(
2880 AArch64Operand::CreateToken(".0", false, S, getContext()));
2881 return false;
2882 }
2883
2884 const MCExpr *ImmVal;
2885 if (parseSymbolicImmVal(ImmVal))
2886 return true;
2887
2888 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2889 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
2890 return false;
2891 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002892 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00002893 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002894 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00002895 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002896 Parser.Lex(); // Eat '='
2897 const MCExpr *SubExprVal;
2898 if (getParser().parseExpression(SubExprVal))
2899 return true;
2900
David Peixottoae5ba762014-07-18 16:05:14 +00002901 if (Operands.size() < 2 ||
2902 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00002903 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00002904
2905 bool IsXReg =
2906 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
2907 Operands[1]->getReg());
2908
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002909 MCContext& Ctx = getContext();
2910 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
2911 // 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 +00002912 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002913 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
2914 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
2915 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
2916 ShiftAmt += 16;
2917 Imm >>= 16;
2918 }
2919 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
2920 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
2921 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00002922 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002923 if (ShiftAmt)
2924 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
2925 ShiftAmt, true, S, E, Ctx));
2926 return false;
2927 }
David Peixottoae5ba762014-07-18 16:05:14 +00002928 APInt Simm = APInt(64, Imm << ShiftAmt);
2929 // check if the immediate is an unsigned or signed 32-bit int for W regs
2930 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
2931 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002932 }
2933 // 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 +00002934 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00002935 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002936 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
2937 return false;
2938 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002939 }
2940}
2941
2942/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
2943/// operands.
2944bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
2945 StringRef Name, SMLoc NameLoc,
2946 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002947 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002948 Name = StringSwitch<StringRef>(Name.lower())
2949 .Case("beq", "b.eq")
2950 .Case("bne", "b.ne")
2951 .Case("bhs", "b.hs")
2952 .Case("bcs", "b.cs")
2953 .Case("blo", "b.lo")
2954 .Case("bcc", "b.cc")
2955 .Case("bmi", "b.mi")
2956 .Case("bpl", "b.pl")
2957 .Case("bvs", "b.vs")
2958 .Case("bvc", "b.vc")
2959 .Case("bhi", "b.hi")
2960 .Case("bls", "b.ls")
2961 .Case("bge", "b.ge")
2962 .Case("blt", "b.lt")
2963 .Case("bgt", "b.gt")
2964 .Case("ble", "b.le")
2965 .Case("bal", "b.al")
2966 .Case("bnv", "b.nv")
2967 .Default(Name);
2968
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002969 // First check for the AArch64-specific .req directive.
2970 if (Parser.getTok().is(AsmToken::Identifier) &&
2971 Parser.getTok().getIdentifier() == ".req") {
2972 parseDirectiveReq(Name, NameLoc);
2973 // We always return 'error' for this, as we're done with this
2974 // statement and don't need to match the 'instruction."
2975 return true;
2976 }
2977
Tim Northover3b0846e2014-05-24 12:50:23 +00002978 // Create the leading tokens for the mnemonic, split by '.' characters.
2979 size_t Start = 0, Next = Name.find('.');
2980 StringRef Head = Name.slice(Start, Next);
2981
2982 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00002983 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
2984 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00002985
2986 Operands.push_back(
2987 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
2988 Mnemonic = Head;
2989
2990 // Handle condition codes for a branch mnemonic
2991 if (Head == "b" && Next != StringRef::npos) {
2992 Start = Next;
2993 Next = Name.find('.', Start + 1);
2994 Head = Name.slice(Start + 1, Next);
2995
2996 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
2997 (Head.data() - Name.data()));
2998 AArch64CC::CondCode CC = parseCondCodeString(Head);
2999 if (CC == AArch64CC::Invalid)
3000 return Error(SuffixLoc, "invalid condition code");
3001 Operands.push_back(
3002 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3003 Operands.push_back(
3004 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3005 }
3006
3007 // Add the remaining tokens in the mnemonic.
3008 while (Next != StringRef::npos) {
3009 Start = Next;
3010 Next = Name.find('.', Start + 1);
3011 Head = Name.slice(Start, Next);
3012 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3013 (Head.data() - Name.data()) + 1);
3014 Operands.push_back(
3015 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3016 }
3017
3018 // Conditional compare instructions have a Condition Code operand, which needs
3019 // to be parsed and an immediate operand created.
3020 bool condCodeFourthOperand =
3021 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3022 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3023 Head == "csinc" || Head == "csinv" || Head == "csneg");
3024
3025 // These instructions are aliases to some of the conditional select
3026 // instructions. However, the condition code is inverted in the aliased
3027 // instruction.
3028 //
3029 // FIXME: Is this the correct way to handle these? Or should the parser
3030 // generate the aliased instructions directly?
3031 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3032 bool condCodeThirdOperand =
3033 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3034
3035 // Read the remaining operands.
3036 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3037 // Read the first operand.
3038 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003039 return true;
3040 }
3041
3042 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003043 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003044 // Parse and remember the operand.
3045 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3046 (N == 3 && condCodeThirdOperand) ||
3047 (N == 2 && condCodeSecondOperand),
3048 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003049 return true;
3050 }
3051
3052 // After successfully parsing some operands there are two special cases to
3053 // consider (i.e. notional operands not separated by commas). Both are due
3054 // to memory specifiers:
3055 // + An RBrac will end an address for load/store/prefetch
3056 // + An '!' will indicate a pre-indexed operation.
3057 //
3058 // It's someone else's responsibility to make sure these tokens are sane
3059 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003060
Nirav Davee833c6c2016-11-08 18:31:04 +00003061 SMLoc RLoc = Parser.getTok().getLoc();
3062 if (parseOptionalToken(AsmToken::RBrac))
3063 Operands.push_back(
3064 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3065 SMLoc ELoc = Parser.getTok().getLoc();
3066 if (parseOptionalToken(AsmToken::Exclaim))
3067 Operands.push_back(
3068 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003069
3070 ++N;
3071 }
3072 }
3073
Nirav Davee833c6c2016-11-08 18:31:04 +00003074 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3075 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003076
Tim Northover3b0846e2014-05-24 12:50:23 +00003077 return false;
3078}
3079
3080// FIXME: This entire function is a giant hack to provide us with decent
3081// operand range validation/diagnostics until TableGen/MC can be extended
3082// to support autogeneration of this kind of validation.
3083bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3084 SmallVectorImpl<SMLoc> &Loc) {
3085 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3086 // Check for indexed addressing modes w/ the base register being the
3087 // same as a destination/source register or pair load where
3088 // the Rt == Rt2. All of those are undefined behaviour.
3089 switch (Inst.getOpcode()) {
3090 case AArch64::LDPSWpre:
3091 case AArch64::LDPWpost:
3092 case AArch64::LDPWpre:
3093 case AArch64::LDPXpost:
3094 case AArch64::LDPXpre: {
3095 unsigned Rt = Inst.getOperand(1).getReg();
3096 unsigned Rt2 = Inst.getOperand(2).getReg();
3097 unsigned Rn = Inst.getOperand(3).getReg();
3098 if (RI->isSubRegisterEq(Rn, Rt))
3099 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3100 "is also a destination");
3101 if (RI->isSubRegisterEq(Rn, Rt2))
3102 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3103 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003104 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003105 }
3106 case AArch64::LDPDi:
3107 case AArch64::LDPQi:
3108 case AArch64::LDPSi:
3109 case AArch64::LDPSWi:
3110 case AArch64::LDPWi:
3111 case AArch64::LDPXi: {
3112 unsigned Rt = Inst.getOperand(0).getReg();
3113 unsigned Rt2 = Inst.getOperand(1).getReg();
3114 if (Rt == Rt2)
3115 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3116 break;
3117 }
3118 case AArch64::LDPDpost:
3119 case AArch64::LDPDpre:
3120 case AArch64::LDPQpost:
3121 case AArch64::LDPQpre:
3122 case AArch64::LDPSpost:
3123 case AArch64::LDPSpre:
3124 case AArch64::LDPSWpost: {
3125 unsigned Rt = Inst.getOperand(1).getReg();
3126 unsigned Rt2 = Inst.getOperand(2).getReg();
3127 if (Rt == Rt2)
3128 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3129 break;
3130 }
3131 case AArch64::STPDpost:
3132 case AArch64::STPDpre:
3133 case AArch64::STPQpost:
3134 case AArch64::STPQpre:
3135 case AArch64::STPSpost:
3136 case AArch64::STPSpre:
3137 case AArch64::STPWpost:
3138 case AArch64::STPWpre:
3139 case AArch64::STPXpost:
3140 case AArch64::STPXpre: {
3141 unsigned Rt = Inst.getOperand(1).getReg();
3142 unsigned Rt2 = Inst.getOperand(2).getReg();
3143 unsigned Rn = Inst.getOperand(3).getReg();
3144 if (RI->isSubRegisterEq(Rn, Rt))
3145 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3146 "is also a source");
3147 if (RI->isSubRegisterEq(Rn, Rt2))
3148 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3149 "is also a source");
3150 break;
3151 }
3152 case AArch64::LDRBBpre:
3153 case AArch64::LDRBpre:
3154 case AArch64::LDRHHpre:
3155 case AArch64::LDRHpre:
3156 case AArch64::LDRSBWpre:
3157 case AArch64::LDRSBXpre:
3158 case AArch64::LDRSHWpre:
3159 case AArch64::LDRSHXpre:
3160 case AArch64::LDRSWpre:
3161 case AArch64::LDRWpre:
3162 case AArch64::LDRXpre:
3163 case AArch64::LDRBBpost:
3164 case AArch64::LDRBpost:
3165 case AArch64::LDRHHpost:
3166 case AArch64::LDRHpost:
3167 case AArch64::LDRSBWpost:
3168 case AArch64::LDRSBXpost:
3169 case AArch64::LDRSHWpost:
3170 case AArch64::LDRSHXpost:
3171 case AArch64::LDRSWpost:
3172 case AArch64::LDRWpost:
3173 case AArch64::LDRXpost: {
3174 unsigned Rt = Inst.getOperand(1).getReg();
3175 unsigned Rn = Inst.getOperand(2).getReg();
3176 if (RI->isSubRegisterEq(Rn, Rt))
3177 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3178 "is also a source");
3179 break;
3180 }
3181 case AArch64::STRBBpost:
3182 case AArch64::STRBpost:
3183 case AArch64::STRHHpost:
3184 case AArch64::STRHpost:
3185 case AArch64::STRWpost:
3186 case AArch64::STRXpost:
3187 case AArch64::STRBBpre:
3188 case AArch64::STRBpre:
3189 case AArch64::STRHHpre:
3190 case AArch64::STRHpre:
3191 case AArch64::STRWpre:
3192 case AArch64::STRXpre: {
3193 unsigned Rt = Inst.getOperand(1).getReg();
3194 unsigned Rn = Inst.getOperand(2).getReg();
3195 if (RI->isSubRegisterEq(Rn, Rt))
3196 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3197 "is also a source");
3198 break;
3199 }
3200 }
3201
3202 // Now check immediate ranges. Separate from the above as there is overlap
3203 // in the instructions being checked and this keeps the nested conditionals
3204 // to a minimum.
3205 switch (Inst.getOpcode()) {
3206 case AArch64::ADDSWri:
3207 case AArch64::ADDSXri:
3208 case AArch64::ADDWri:
3209 case AArch64::ADDXri:
3210 case AArch64::SUBSWri:
3211 case AArch64::SUBSXri:
3212 case AArch64::SUBWri:
3213 case AArch64::SUBXri: {
3214 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3215 // some slight duplication here.
3216 if (Inst.getOperand(2).isExpr()) {
3217 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3218 AArch64MCExpr::VariantKind ELFRefKind;
3219 MCSymbolRefExpr::VariantKind DarwinRefKind;
3220 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003221 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3222
3223 // Only allow these with ADDXri.
3224 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3225 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3226 Inst.getOpcode() == AArch64::ADDXri)
3227 return false;
3228
3229 // Only allow these with ADDXri/ADDWri
3230 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3231 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3232 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3233 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3234 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3235 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3236 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3237 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3238 (Inst.getOpcode() == AArch64::ADDXri ||
3239 Inst.getOpcode() == AArch64::ADDWri))
3240 return false;
3241
3242 // Don't allow symbol refs in the immediate field otherwise
3243 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3244 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3245 // 'cmp w0, 'borked')
3246 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003247 }
Diana Picusc93518d2016-10-11 09:17:47 +00003248 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003249 }
3250 return false;
3251 }
3252 default:
3253 return false;
3254 }
3255}
3256
3257bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3258 switch (ErrCode) {
3259 case Match_MissingFeature:
3260 return Error(Loc,
3261 "instruction requires a CPU feature not currently enabled");
3262 case Match_InvalidOperand:
3263 return Error(Loc, "invalid operand for instruction");
3264 case Match_InvalidSuffix:
3265 return Error(Loc, "invalid type suffix for instruction");
3266 case Match_InvalidCondCode:
3267 return Error(Loc, "expected AArch64 condition code");
3268 case Match_AddSubRegExtendSmall:
3269 return Error(Loc,
3270 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3271 case Match_AddSubRegExtendLarge:
3272 return Error(Loc,
3273 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3274 case Match_AddSubSecondSource:
3275 return Error(Loc,
3276 "expected compatible register, symbol or integer in range [0, 4095]");
3277 case Match_LogicalSecondSource:
3278 return Error(Loc, "expected compatible register or logical immediate");
3279 case Match_InvalidMovImm32Shift:
3280 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3281 case Match_InvalidMovImm64Shift:
3282 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3283 case Match_AddSubRegShift32:
3284 return Error(Loc,
3285 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3286 case Match_AddSubRegShift64:
3287 return Error(Loc,
3288 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3289 case Match_InvalidFPImm:
3290 return Error(Loc,
3291 "expected compatible register or floating-point constant");
3292 case Match_InvalidMemoryIndexedSImm9:
3293 return Error(Loc, "index must be an integer in range [-256, 255].");
3294 case Match_InvalidMemoryIndexed4SImm7:
3295 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3296 case Match_InvalidMemoryIndexed8SImm7:
3297 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3298 case Match_InvalidMemoryIndexed16SImm7:
3299 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3300 case Match_InvalidMemoryWExtend8:
3301 return Error(Loc,
3302 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3303 case Match_InvalidMemoryWExtend16:
3304 return Error(Loc,
3305 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3306 case Match_InvalidMemoryWExtend32:
3307 return Error(Loc,
3308 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3309 case Match_InvalidMemoryWExtend64:
3310 return Error(Loc,
3311 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3312 case Match_InvalidMemoryWExtend128:
3313 return Error(Loc,
3314 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3315 case Match_InvalidMemoryXExtend8:
3316 return Error(Loc,
3317 "expected 'lsl' or 'sxtx' with optional shift of #0");
3318 case Match_InvalidMemoryXExtend16:
3319 return Error(Loc,
3320 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3321 case Match_InvalidMemoryXExtend32:
3322 return Error(Loc,
3323 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3324 case Match_InvalidMemoryXExtend64:
3325 return Error(Loc,
3326 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3327 case Match_InvalidMemoryXExtend128:
3328 return Error(Loc,
3329 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3330 case Match_InvalidMemoryIndexed1:
3331 return Error(Loc, "index must be an integer in range [0, 4095].");
3332 case Match_InvalidMemoryIndexed2:
3333 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3334 case Match_InvalidMemoryIndexed4:
3335 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3336 case Match_InvalidMemoryIndexed8:
3337 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3338 case Match_InvalidMemoryIndexed16:
3339 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003340 case Match_InvalidImm0_1:
3341 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003342 case Match_InvalidImm0_7:
3343 return Error(Loc, "immediate must be an integer in range [0, 7].");
3344 case Match_InvalidImm0_15:
3345 return Error(Loc, "immediate must be an integer in range [0, 15].");
3346 case Match_InvalidImm0_31:
3347 return Error(Loc, "immediate must be an integer in range [0, 31].");
3348 case Match_InvalidImm0_63:
3349 return Error(Loc, "immediate must be an integer in range [0, 63].");
3350 case Match_InvalidImm0_127:
3351 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003352 case Match_InvalidImm0_255:
3353 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003354 case Match_InvalidImm0_65535:
3355 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3356 case Match_InvalidImm1_8:
3357 return Error(Loc, "immediate must be an integer in range [1, 8].");
3358 case Match_InvalidImm1_16:
3359 return Error(Loc, "immediate must be an integer in range [1, 16].");
3360 case Match_InvalidImm1_32:
3361 return Error(Loc, "immediate must be an integer in range [1, 32].");
3362 case Match_InvalidImm1_64:
3363 return Error(Loc, "immediate must be an integer in range [1, 64].");
3364 case Match_InvalidIndex1:
3365 return Error(Loc, "expected lane specifier '[1]'");
3366 case Match_InvalidIndexB:
3367 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3368 case Match_InvalidIndexH:
3369 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3370 case Match_InvalidIndexS:
3371 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3372 case Match_InvalidIndexD:
3373 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3374 case Match_InvalidLabel:
3375 return Error(Loc, "expected label or encodable integer pc offset");
3376 case Match_MRS:
3377 return Error(Loc, "expected readable system register");
3378 case Match_MSR:
3379 return Error(Loc, "expected writable system register or pstate");
3380 case Match_MnemonicFail:
3381 return Error(Loc, "unrecognized instruction mnemonic");
3382 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003383 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003384 }
3385}
3386
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003387static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003388
3389bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3390 OperandVector &Operands,
3391 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003392 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003393 bool MatchingInlineAsm) {
3394 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003395 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3396 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003397
David Blaikie960ea3f2014-06-08 16:18:35 +00003398 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003399 unsigned NumOperands = Operands.size();
3400
3401 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003402 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3403 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3404 if (Op2.isReg() && Op3.isImm()) {
3405 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003406 if (Op3CE) {
3407 uint64_t Op3Val = Op3CE->getValue();
3408 uint64_t NewOp3Val = 0;
3409 uint64_t NewOp4Val = 0;
3410 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003411 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003412 NewOp3Val = (32 - Op3Val) & 0x1f;
3413 NewOp4Val = 31 - Op3Val;
3414 } else {
3415 NewOp3Val = (64 - Op3Val) & 0x3f;
3416 NewOp4Val = 63 - Op3Val;
3417 }
3418
Jim Grosbach13760bd2015-05-30 01:25:56 +00003419 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3420 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003421
3422 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003423 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003424 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003425 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3426 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3427 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003428 }
3429 }
Tim Northover03b99f62015-04-30 18:28:58 +00003430 } else if (NumOperands == 4 && Tok == "bfc") {
3431 // FIXME: Horrible hack to handle BFC->BFM alias.
3432 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3433 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3434 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3435
3436 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3437 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3438 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3439
3440 if (LSBCE && WidthCE) {
3441 uint64_t LSB = LSBCE->getValue();
3442 uint64_t Width = WidthCE->getValue();
3443
3444 uint64_t RegWidth = 0;
3445 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3446 Op1.getReg()))
3447 RegWidth = 64;
3448 else
3449 RegWidth = 32;
3450
3451 if (LSB >= RegWidth)
3452 return Error(LSBOp.getStartLoc(),
3453 "expected integer in range [0, 31]");
3454 if (Width < 1 || Width > RegWidth)
3455 return Error(WidthOp.getStartLoc(),
3456 "expected integer in range [1, 32]");
3457
3458 uint64_t ImmR = 0;
3459 if (RegWidth == 32)
3460 ImmR = (32 - LSB) & 0x1f;
3461 else
3462 ImmR = (64 - LSB) & 0x3f;
3463
3464 uint64_t ImmS = Width - 1;
3465
3466 if (ImmR != 0 && ImmS >= ImmR)
3467 return Error(WidthOp.getStartLoc(),
3468 "requested insert overflows register");
3469
Jim Grosbach13760bd2015-05-30 01:25:56 +00003470 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3471 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003472 Operands[0] = AArch64Operand::CreateToken(
3473 "bfm", false, Op.getStartLoc(), getContext());
3474 Operands[2] = AArch64Operand::CreateReg(
3475 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3476 SMLoc(), getContext());
3477 Operands[3] = AArch64Operand::CreateImm(
3478 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3479 Operands.emplace_back(
3480 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3481 WidthOp.getEndLoc(), getContext()));
3482 }
3483 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003484 } else if (NumOperands == 5) {
3485 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3486 // UBFIZ -> UBFM aliases.
3487 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003488 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3489 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3490 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003491
David Blaikie960ea3f2014-06-08 16:18:35 +00003492 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3493 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3494 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003495
3496 if (Op3CE && Op4CE) {
3497 uint64_t Op3Val = Op3CE->getValue();
3498 uint64_t Op4Val = Op4CE->getValue();
3499
3500 uint64_t RegWidth = 0;
3501 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003502 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003503 RegWidth = 64;
3504 else
3505 RegWidth = 32;
3506
3507 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003508 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003509 "expected integer in range [0, 31]");
3510 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003511 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003512 "expected integer in range [1, 32]");
3513
3514 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003515 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003516 NewOp3Val = (32 - Op3Val) & 0x1f;
3517 else
3518 NewOp3Val = (64 - Op3Val) & 0x3f;
3519
3520 uint64_t NewOp4Val = Op4Val - 1;
3521
3522 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003523 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003524 "requested insert overflows register");
3525
3526 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003527 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003528 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003529 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003530 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003531 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003532 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003533 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003534 if (Tok == "bfi")
3535 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003536 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003537 else if (Tok == "sbfiz")
3538 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003539 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003540 else if (Tok == "ubfiz")
3541 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003542 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003543 else
3544 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003545 }
3546 }
3547
3548 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3549 // UBFX -> UBFM aliases.
3550 } else if (NumOperands == 5 &&
3551 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003552 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3553 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3554 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003555
David Blaikie960ea3f2014-06-08 16:18:35 +00003556 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3557 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3558 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003559
3560 if (Op3CE && Op4CE) {
3561 uint64_t Op3Val = Op3CE->getValue();
3562 uint64_t Op4Val = Op4CE->getValue();
3563
3564 uint64_t RegWidth = 0;
3565 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003566 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003567 RegWidth = 64;
3568 else
3569 RegWidth = 32;
3570
3571 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003572 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003573 "expected integer in range [0, 31]");
3574 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003575 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003576 "expected integer in range [1, 32]");
3577
3578 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3579
3580 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003581 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003582 "requested extract overflows register");
3583
3584 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003585 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003586 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003587 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003588 if (Tok == "bfxil")
3589 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003590 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003591 else if (Tok == "sbfx")
3592 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003593 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003594 else if (Tok == "ubfx")
3595 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003596 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003597 else
3598 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003599 }
3600 }
3601 }
3602 }
3603 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3604 // InstAlias can't quite handle this since the reg classes aren't
3605 // subclasses.
3606 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3607 // The source register can be Wn here, but the matcher expects a
3608 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003609 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3610 if (Op.isReg()) {
3611 unsigned Reg = getXRegFromWReg(Op.getReg());
3612 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3613 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003614 }
3615 }
3616 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3617 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003618 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3619 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003620 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003621 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003622 // The source register can be Wn here, but the matcher expects a
3623 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003624 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3625 if (Op.isReg()) {
3626 unsigned Reg = getXRegFromWReg(Op.getReg());
3627 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3628 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003629 }
3630 }
3631 }
3632 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3633 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003634 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3635 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003636 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003637 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003638 // The source register can be Wn here, but the matcher expects a
3639 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003640 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3641 if (Op.isReg()) {
3642 unsigned Reg = getWRegFromXReg(Op.getReg());
3643 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3644 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003645 }
3646 }
3647 }
3648
3649 // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
3650 if (NumOperands == 3 && Tok == "fmov") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003651 AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
3652 AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
3653 if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003654 unsigned zreg =
Oliver Stannardb25914e2015-11-27 13:04:48 +00003655 !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003656 RegOp.getReg())
Tim Northover3b0846e2014-05-24 12:50:23 +00003657 ? AArch64::WZR
3658 : AArch64::XZR;
David Blaikie960ea3f2014-06-08 16:18:35 +00003659 Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
3660 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003661 }
3662 }
3663
3664 MCInst Inst;
3665 // First try to match against the secondary set of tables containing the
3666 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3667 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003668 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003669
3670 // If that fails, try against the alternate table containing long-form NEON:
3671 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003672 if (MatchResult != Match_Success) {
3673 // But first, save the short-form match result: we can use it in case the
3674 // long-form match also fails.
3675 auto ShortFormNEONErrorInfo = ErrorInfo;
3676 auto ShortFormNEONMatchResult = MatchResult;
3677
Tim Northover3b0846e2014-05-24 12:50:23 +00003678 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003679 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003680
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003681 // Now, both matches failed, and the long-form match failed on the mnemonic
3682 // suffix token operand. The short-form match failure is probably more
3683 // relevant: use it instead.
3684 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003685 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003686 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3687 MatchResult = ShortFormNEONMatchResult;
3688 ErrorInfo = ShortFormNEONErrorInfo;
3689 }
3690 }
3691
Tim Northover3b0846e2014-05-24 12:50:23 +00003692 switch (MatchResult) {
3693 case Match_Success: {
3694 // Perform range checking and other semantic validations
3695 SmallVector<SMLoc, 8> OperandLocs;
3696 NumOperands = Operands.size();
3697 for (unsigned i = 1; i < NumOperands; ++i)
3698 OperandLocs.push_back(Operands[i]->getStartLoc());
3699 if (validateInstruction(Inst, OperandLocs))
3700 return true;
3701
3702 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003703 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003704 return false;
3705 }
3706 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003707 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003708 // Special case the error message for the very common case where only
3709 // a single subtarget feature is missing (neon, e.g.).
3710 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003711 uint64_t Mask = 1;
3712 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3713 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003714 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003715 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003716 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003717 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003718 }
3719 return Error(IDLoc, Msg);
3720 }
3721 case Match_MnemonicFail:
3722 return showMatchError(IDLoc, MatchResult);
3723 case Match_InvalidOperand: {
3724 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003725
Tim Northover26bb14e2014-08-18 11:49:42 +00003726 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003727 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003728 return Error(IDLoc, "too few operands for instruction",
3729 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003730
David Blaikie960ea3f2014-06-08 16:18:35 +00003731 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003732 if (ErrorLoc == SMLoc())
3733 ErrorLoc = IDLoc;
3734 }
3735 // If the match failed on a suffix token operand, tweak the diagnostic
3736 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003737 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
3738 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00003739 MatchResult = Match_InvalidSuffix;
3740
3741 return showMatchError(ErrorLoc, MatchResult);
3742 }
3743 case Match_InvalidMemoryIndexed1:
3744 case Match_InvalidMemoryIndexed2:
3745 case Match_InvalidMemoryIndexed4:
3746 case Match_InvalidMemoryIndexed8:
3747 case Match_InvalidMemoryIndexed16:
3748 case Match_InvalidCondCode:
3749 case Match_AddSubRegExtendSmall:
3750 case Match_AddSubRegExtendLarge:
3751 case Match_AddSubSecondSource:
3752 case Match_LogicalSecondSource:
3753 case Match_AddSubRegShift32:
3754 case Match_AddSubRegShift64:
3755 case Match_InvalidMovImm32Shift:
3756 case Match_InvalidMovImm64Shift:
3757 case Match_InvalidFPImm:
3758 case Match_InvalidMemoryWExtend8:
3759 case Match_InvalidMemoryWExtend16:
3760 case Match_InvalidMemoryWExtend32:
3761 case Match_InvalidMemoryWExtend64:
3762 case Match_InvalidMemoryWExtend128:
3763 case Match_InvalidMemoryXExtend8:
3764 case Match_InvalidMemoryXExtend16:
3765 case Match_InvalidMemoryXExtend32:
3766 case Match_InvalidMemoryXExtend64:
3767 case Match_InvalidMemoryXExtend128:
3768 case Match_InvalidMemoryIndexed4SImm7:
3769 case Match_InvalidMemoryIndexed8SImm7:
3770 case Match_InvalidMemoryIndexed16SImm7:
3771 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003772 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003773 case Match_InvalidImm0_7:
3774 case Match_InvalidImm0_15:
3775 case Match_InvalidImm0_31:
3776 case Match_InvalidImm0_63:
3777 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003778 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00003779 case Match_InvalidImm0_65535:
3780 case Match_InvalidImm1_8:
3781 case Match_InvalidImm1_16:
3782 case Match_InvalidImm1_32:
3783 case Match_InvalidImm1_64:
3784 case Match_InvalidIndex1:
3785 case Match_InvalidIndexB:
3786 case Match_InvalidIndexH:
3787 case Match_InvalidIndexS:
3788 case Match_InvalidIndexD:
3789 case Match_InvalidLabel:
3790 case Match_MSR:
3791 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00003792 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003793 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003794 // Any time we get here, there's nothing fancy to do. Just get the
3795 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00003796 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003797 if (ErrorLoc == SMLoc())
3798 ErrorLoc = IDLoc;
3799 return showMatchError(ErrorLoc, MatchResult);
3800 }
3801 }
3802
3803 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003804}
3805
3806/// ParseDirective parses the arm specific directives
3807bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00003808 const MCObjectFileInfo::Environment Format =
3809 getContext().getObjectFileInfo()->getObjectFileType();
3810 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
3811 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00003812
Tim Northover3b0846e2014-05-24 12:50:23 +00003813 StringRef IDVal = DirectiveID.getIdentifier();
3814 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003815 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00003816 parseDirectiveArch(Loc);
3817 else if (IDVal == ".cpu")
3818 parseDirectiveCPU(Loc);
3819 else if (IDVal == ".hword")
3820 parseDirectiveWord(2, Loc);
3821 else if (IDVal == ".word")
3822 parseDirectiveWord(4, Loc);
3823 else if (IDVal == ".xword")
3824 parseDirectiveWord(8, Loc);
3825 else if (IDVal == ".tlsdesccall")
3826 parseDirectiveTLSDescCall(Loc);
3827 else if (IDVal == ".ltorg" || IDVal == ".pool")
3828 parseDirectiveLtorg(Loc);
3829 else if (IDVal == ".unreq")
3830 parseDirectiveUnreq(Loc);
3831 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00003832 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00003833 parseDirectiveInst(Loc);
3834 else
3835 return true;
3836 } else if (IDVal == MCLOHDirectiveName())
3837 parseDirectiveLOH(IDVal, Loc);
3838 else
3839 return true;
3840 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003841}
3842
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003843static const struct {
3844 const char *Name;
3845 const FeatureBitset Features;
3846} ExtensionMap[] = {
3847 { "crc", {AArch64::FeatureCRC} },
3848 { "crypto", {AArch64::FeatureCrypto} },
3849 { "fp", {AArch64::FeatureFPARMv8} },
3850 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003851 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00003852 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003853
3854 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003855 { "pan", {} },
3856 { "lor", {} },
3857 { "rdma", {} },
3858 { "profile", {} },
3859};
3860
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003861/// parseDirectiveArch
3862/// ::= .arch token
3863bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
3864 SMLoc ArchLoc = getLoc();
3865
3866 StringRef Arch, ExtensionString;
3867 std::tie(Arch, ExtensionString) =
3868 getParser().parseStringToEndOfStatement().trim().split('+');
3869
3870 unsigned ID = AArch64::parseArch(Arch);
Nirav Davee833c6c2016-11-08 18:31:04 +00003871 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
3872 return Error(ArchLoc, "unknown arch name");
3873
3874 if (parseToken(AsmToken::EndOfStatement))
3875 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003876
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003877 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00003878 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003879 AArch64::getArchFeatures(ID, AArch64Features);
3880 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
3881 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003882
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003883 MCSubtargetInfo &STI = copySTI();
3884 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
3885 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
3886
3887 SmallVector<StringRef, 4> RequestedExtensions;
3888 if (!ExtensionString.empty())
3889 ExtensionString.split(RequestedExtensions, '+');
3890
3891 FeatureBitset Features = STI.getFeatureBits();
3892 for (auto Name : RequestedExtensions) {
3893 bool EnableFeature = true;
3894
3895 if (Name.startswith_lower("no")) {
3896 EnableFeature = false;
3897 Name = Name.substr(2);
3898 }
3899
3900 for (const auto &Extension : ExtensionMap) {
3901 if (Extension.Name != Name)
3902 continue;
3903
3904 if (Extension.Features.none())
3905 report_fatal_error("unsupported architectural extension: " + Name);
3906
3907 FeatureBitset ToggleFeatures = EnableFeature
3908 ? (~Features & Extension.Features)
3909 : ( Features & Extension.Features);
3910 uint64_t Features =
3911 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
3912 setAvailableFeatures(Features);
3913 break;
3914 }
3915 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003916 return false;
3917}
3918
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003919/// parseDirectiveCPU
3920/// ::= .cpu id
3921bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
3922 SMLoc CPULoc = getLoc();
3923
3924 StringRef CPU, ExtensionString;
3925 std::tie(CPU, ExtensionString) =
3926 getParser().parseStringToEndOfStatement().trim().split('+');
3927
Nirav Davee833c6c2016-11-08 18:31:04 +00003928 if (parseToken(AsmToken::EndOfStatement))
3929 return true;
3930
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003931 SmallVector<StringRef, 4> RequestedExtensions;
3932 if (!ExtensionString.empty())
3933 ExtensionString.split(RequestedExtensions, '+');
3934
3935 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
3936 // once that is tablegen'ed
3937 if (!getSTI().isCPUStringValid(CPU)) {
3938 Error(CPULoc, "unknown CPU name");
3939 return false;
3940 }
3941
3942 MCSubtargetInfo &STI = copySTI();
3943 STI.setDefaultFeatures(CPU, "");
3944
3945 FeatureBitset Features = STI.getFeatureBits();
3946 for (auto Name : RequestedExtensions) {
3947 bool EnableFeature = true;
3948
3949 if (Name.startswith_lower("no")) {
3950 EnableFeature = false;
3951 Name = Name.substr(2);
3952 }
3953
3954 for (const auto &Extension : ExtensionMap) {
3955 if (Extension.Name != Name)
3956 continue;
3957
3958 if (Extension.Features.none())
3959 report_fatal_error("unsupported architectural extension: " + Name);
3960
3961 FeatureBitset ToggleFeatures = EnableFeature
3962 ? (~Features & Extension.Features)
3963 : ( Features & Extension.Features);
3964 uint64_t Features =
3965 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
3966 setAvailableFeatures(Features);
3967
3968 break;
3969 }
3970 }
3971 return false;
3972}
3973
Tim Northover3b0846e2014-05-24 12:50:23 +00003974/// parseDirectiveWord
3975/// ::= .word [ expression (, expression)* ]
3976bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003977 auto parseOp = [&]() -> bool {
3978 const MCExpr *Value;
3979 if (getParser().parseExpression(Value))
3980 return true;
3981 getParser().getStreamer().EmitValue(Value, Size, L);
3982 return false;
3983 };
Tim Northover3b0846e2014-05-24 12:50:23 +00003984
Nirav Davee833c6c2016-11-08 18:31:04 +00003985 if (parseMany(parseOp))
3986 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003987 return false;
3988}
3989
Chad Rosierdcd2a302014-10-22 20:35:57 +00003990/// parseDirectiveInst
3991/// ::= .inst opcode [, ...]
3992bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003993 if (getLexer().is(AsmToken::EndOfStatement))
3994 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00003995
Nirav Davee833c6c2016-11-08 18:31:04 +00003996 auto parseOp = [&]() -> bool {
3997 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00003998 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00003999 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4000 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004001 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004002 if (check(!Value, L, "expected constant expression"))
4003 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004004 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004005 return false;
4006 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004007
Nirav Davee833c6c2016-11-08 18:31:04 +00004008 if (parseMany(parseOp))
4009 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004010 return false;
4011}
4012
Tim Northover3b0846e2014-05-24 12:50:23 +00004013// parseDirectiveTLSDescCall:
4014// ::= .tlsdesccall symbol
4015bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4016 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004017 if (check(getParser().parseIdentifier(Name), L,
4018 "expected symbol after directive") ||
4019 parseToken(AsmToken::EndOfStatement))
4020 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004021
Jim Grosbach6f482002015-05-18 18:43:14 +00004022 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004023 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4024 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004025
4026 MCInst Inst;
4027 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004028 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004029
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004030 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004031 return false;
4032}
4033
4034/// ::= .loh <lohName | lohId> label1, ..., labelN
4035/// The number of arguments depends on the loh identifier.
4036bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004037 MCLOHType Kind;
4038 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4039 if (getParser().getTok().isNot(AsmToken::Integer))
4040 return TokError("expected an identifier or a number in directive");
4041 // We successfully get a numeric value for the identifier.
4042 // Check if it is valid.
4043 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004044 if (Id <= -1U && !isValidMCLOHType(Id))
4045 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004046 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004047 } else {
4048 StringRef Name = getTok().getIdentifier();
4049 // We successfully parse an identifier.
4050 // Check if it is a recognized one.
4051 int Id = MCLOHNameToId(Name);
4052
4053 if (Id == -1)
4054 return TokError("invalid identifier in directive");
4055 Kind = (MCLOHType)Id;
4056 }
4057 // Consume the identifier.
4058 Lex();
4059 // Get the number of arguments of this LOH.
4060 int NbArgs = MCLOHIdToNbArgs(Kind);
4061
4062 assert(NbArgs != -1 && "Invalid number of arguments");
4063
4064 SmallVector<MCSymbol *, 3> Args;
4065 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4066 StringRef Name;
4067 if (getParser().parseIdentifier(Name))
4068 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004069 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004070
4071 if (Idx + 1 == NbArgs)
4072 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004073 if (parseToken(AsmToken::Comma,
4074 "unexpected token in '" + Twine(IDVal) + "' directive"))
4075 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004076 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004077 if (parseToken(AsmToken::EndOfStatement,
4078 "unexpected token in '" + Twine(IDVal) + "' directive"))
4079 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004080
4081 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4082 return false;
4083}
4084
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004085/// parseDirectiveLtorg
4086/// ::= .ltorg | .pool
4087bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004088 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4089 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004090 getTargetStreamer().emitCurrentConstantPool();
4091 return false;
4092}
4093
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004094/// parseDirectiveReq
4095/// ::= name .req registername
4096bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004097 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004098 Parser.Lex(); // Eat the '.req' token.
4099 SMLoc SRegLoc = getLoc();
4100 unsigned RegNum = tryParseRegister();
4101 bool IsVector = false;
4102
4103 if (RegNum == static_cast<unsigned>(-1)) {
4104 StringRef Kind;
4105 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004106 if (!Kind.empty())
4107 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004108 IsVector = true;
4109 }
4110
Nirav Dave2364748a2016-09-16 18:30:20 +00004111 if (RegNum == static_cast<unsigned>(-1))
4112 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004113
4114 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004115 if (parseToken(AsmToken::EndOfStatement,
4116 "unexpected input in .req directive"))
4117 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004118
4119 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004120 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004121 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4122
Nirav Dave2364748a2016-09-16 18:30:20 +00004123 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004124}
4125
4126/// parseDirectiveUneq
4127/// ::= .unreq registername
4128bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004129 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004130 if (getTok().isNot(AsmToken::Identifier))
4131 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004132 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4133 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004134 if (parseToken(AsmToken::EndOfStatement))
4135 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004136 return false;
4137}
4138
Tim Northover3b0846e2014-05-24 12:50:23 +00004139bool
4140AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4141 AArch64MCExpr::VariantKind &ELFRefKind,
4142 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4143 int64_t &Addend) {
4144 ELFRefKind = AArch64MCExpr::VK_INVALID;
4145 DarwinRefKind = MCSymbolRefExpr::VK_None;
4146 Addend = 0;
4147
4148 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4149 ELFRefKind = AE->getKind();
4150 Expr = AE->getSubExpr();
4151 }
4152
4153 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4154 if (SE) {
4155 // It's a simple symbol reference with no addend.
4156 DarwinRefKind = SE->getKind();
4157 return true;
4158 }
4159
4160 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4161 if (!BE)
4162 return false;
4163
4164 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4165 if (!SE)
4166 return false;
4167 DarwinRefKind = SE->getKind();
4168
4169 if (BE->getOpcode() != MCBinaryExpr::Add &&
4170 BE->getOpcode() != MCBinaryExpr::Sub)
4171 return false;
4172
4173 // See if the addend is is a constant, otherwise there's more going
4174 // on here than we can deal with.
4175 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4176 if (!AddendExpr)
4177 return false;
4178
4179 Addend = AddendExpr->getValue();
4180 if (BE->getOpcode() == MCBinaryExpr::Sub)
4181 Addend = -Addend;
4182
4183 // It's some symbol reference + a constant addend, but really
4184 // shouldn't use both Darwin and ELF syntax.
4185 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4186 DarwinRefKind == MCSymbolRefExpr::VK_None;
4187}
4188
4189/// Force static initialization.
4190extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004191 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4192 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4193 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004194}
4195
4196#define GET_REGISTER_MATCHER
4197#define GET_SUBTARGET_FEATURE_NAME
4198#define GET_MATCHER_IMPLEMENTATION
4199#include "AArch64GenAsmMatcher.inc"
4200
4201// Define this matcher function after the auto-generated include so we
4202// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004203unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004204 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004205 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004206 // If the kind is a token for a literal immediate, check if our asm
4207 // operand matches. This is for InstAliases which have a fixed-value
4208 // immediate in the syntax.
4209 int64_t ExpectedVal;
4210 switch (Kind) {
4211 default:
4212 return Match_InvalidOperand;
4213 case MCK__35_0:
4214 ExpectedVal = 0;
4215 break;
4216 case MCK__35_1:
4217 ExpectedVal = 1;
4218 break;
4219 case MCK__35_12:
4220 ExpectedVal = 12;
4221 break;
4222 case MCK__35_16:
4223 ExpectedVal = 16;
4224 break;
4225 case MCK__35_2:
4226 ExpectedVal = 2;
4227 break;
4228 case MCK__35_24:
4229 ExpectedVal = 24;
4230 break;
4231 case MCK__35_3:
4232 ExpectedVal = 3;
4233 break;
4234 case MCK__35_32:
4235 ExpectedVal = 32;
4236 break;
4237 case MCK__35_4:
4238 ExpectedVal = 4;
4239 break;
4240 case MCK__35_48:
4241 ExpectedVal = 48;
4242 break;
4243 case MCK__35_6:
4244 ExpectedVal = 6;
4245 break;
4246 case MCK__35_64:
4247 ExpectedVal = 64;
4248 break;
4249 case MCK__35_8:
4250 ExpectedVal = 8;
4251 break;
4252 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004253 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004254 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004255 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004256 if (!CE)
4257 return Match_InvalidOperand;
4258 if (CE->getValue() == ExpectedVal)
4259 return Match_Success;
4260 return Match_InvalidOperand;
4261}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004262
Alex Bradbury58eba092016-11-01 16:32:05 +00004263OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004264AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4265
4266 SMLoc S = getLoc();
4267
4268 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4269 Error(S, "expected register");
4270 return MatchOperand_ParseFail;
4271 }
4272
4273 int FirstReg = tryParseRegister();
4274 if (FirstReg == -1) {
4275 return MatchOperand_ParseFail;
4276 }
4277 const MCRegisterClass &WRegClass =
4278 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4279 const MCRegisterClass &XRegClass =
4280 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4281
4282 bool isXReg = XRegClass.contains(FirstReg),
4283 isWReg = WRegClass.contains(FirstReg);
4284 if (!isXReg && !isWReg) {
4285 Error(S, "expected first even register of a "
4286 "consecutive same-size even/odd register pair");
4287 return MatchOperand_ParseFail;
4288 }
4289
4290 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4291 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4292
4293 if (FirstEncoding & 0x1) {
4294 Error(S, "expected first even register of a "
4295 "consecutive same-size even/odd register pair");
4296 return MatchOperand_ParseFail;
4297 }
4298
4299 SMLoc M = getLoc();
4300 if (getParser().getTok().isNot(AsmToken::Comma)) {
4301 Error(M, "expected comma");
4302 return MatchOperand_ParseFail;
4303 }
4304 // Eat the comma
4305 getParser().Lex();
4306
4307 SMLoc E = getLoc();
4308 int SecondReg = tryParseRegister();
4309 if (SecondReg ==-1) {
4310 return MatchOperand_ParseFail;
4311 }
4312
Eugene Zelenko049b0172017-01-06 00:30:53 +00004313 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004314 (isXReg && !XRegClass.contains(SecondReg)) ||
4315 (isWReg && !WRegClass.contains(SecondReg))) {
4316 Error(E,"expected second odd register of a "
4317 "consecutive same-size even/odd register pair");
4318 return MatchOperand_ParseFail;
4319 }
Joel Jones504bf332016-10-24 13:37:13 +00004320
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004321 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004322 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004323 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4324 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4325 } else {
4326 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4327 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4328 }
4329
4330 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4331 getContext()));
4332
4333 return MatchOperand_Success;
4334}