blob: cbab68979c56783aa6d55957c4a09430dcd9ad14 [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();
2103 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002104 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002105 if (isNegative)
2106 RealVal.changeSign();
2107
Tim Northover3b0846e2014-05-24 12:50:23 +00002108 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002109 int Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2110 Parser.Lex(); // Eat the token.
2111 // Check for out of range values. As an exception, we let Zero through,
2112 // as we handle that special case in post-processing before matching in
2113 // order to use the zero register for it.
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002114 if (Val == -1 && !RealVal.isPosZero()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002115 TokError("expected compatible register or floating-point constant");
2116 return MatchOperand_ParseFail;
2117 }
2118 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2119 return MatchOperand_Success;
2120 }
2121 if (Tok.is(AsmToken::Integer)) {
2122 int64_t Val;
2123 if (!isNegative && Tok.getString().startswith("0x")) {
2124 Val = Tok.getIntVal();
2125 if (Val > 255 || Val < 0) {
2126 TokError("encoded floating point value out of range");
2127 return MatchOperand_ParseFail;
2128 }
2129 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002130 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002131 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2132 // If we had a '-' in front, toggle the sign bit.
2133 IntVal ^= (uint64_t)isNegative << 63;
2134 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2135 }
2136 Parser.Lex(); // Eat the token.
2137 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2138 return MatchOperand_Success;
2139 }
2140
2141 if (!Hash)
2142 return MatchOperand_NoMatch;
2143
2144 TokError("invalid floating point immediate");
2145 return MatchOperand_ParseFail;
2146}
2147
2148/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002149OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002150AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002151 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002152 SMLoc S = getLoc();
2153
2154 if (Parser.getTok().is(AsmToken::Hash))
2155 Parser.Lex(); // Eat '#'
2156 else if (Parser.getTok().isNot(AsmToken::Integer))
2157 // Operand should start from # or should be integer, emit error otherwise.
2158 return MatchOperand_NoMatch;
2159
2160 const MCExpr *Imm;
2161 if (parseSymbolicImmVal(Imm))
2162 return MatchOperand_ParseFail;
2163 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2164 uint64_t ShiftAmount = 0;
2165 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2166 if (MCE) {
2167 int64_t Val = MCE->getValue();
2168 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002169 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002170 ShiftAmount = 12;
2171 }
2172 }
2173 SMLoc E = Parser.getTok().getLoc();
2174 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2175 getContext()));
2176 return MatchOperand_Success;
2177 }
2178
2179 // Eat ','
2180 Parser.Lex();
2181
2182 // The optional operand must be "lsl #N" where N is non-negative.
2183 if (!Parser.getTok().is(AsmToken::Identifier) ||
2184 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2185 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2186 return MatchOperand_ParseFail;
2187 }
2188
2189 // Eat 'lsl'
2190 Parser.Lex();
2191
Nirav Davee833c6c2016-11-08 18:31:04 +00002192 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002193
2194 if (Parser.getTok().isNot(AsmToken::Integer)) {
2195 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2196 return MatchOperand_ParseFail;
2197 }
2198
2199 int64_t ShiftAmount = Parser.getTok().getIntVal();
2200
2201 if (ShiftAmount < 0) {
2202 Error(Parser.getTok().getLoc(), "positive shift amount required");
2203 return MatchOperand_ParseFail;
2204 }
2205 Parser.Lex(); // Eat the number
2206
2207 SMLoc E = Parser.getTok().getLoc();
2208 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2209 S, E, getContext()));
2210 return MatchOperand_Success;
2211}
2212
2213/// parseCondCodeString - Parse a Condition Code string.
2214AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2215 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2216 .Case("eq", AArch64CC::EQ)
2217 .Case("ne", AArch64CC::NE)
2218 .Case("cs", AArch64CC::HS)
2219 .Case("hs", AArch64CC::HS)
2220 .Case("cc", AArch64CC::LO)
2221 .Case("lo", AArch64CC::LO)
2222 .Case("mi", AArch64CC::MI)
2223 .Case("pl", AArch64CC::PL)
2224 .Case("vs", AArch64CC::VS)
2225 .Case("vc", AArch64CC::VC)
2226 .Case("hi", AArch64CC::HI)
2227 .Case("ls", AArch64CC::LS)
2228 .Case("ge", AArch64CC::GE)
2229 .Case("lt", AArch64CC::LT)
2230 .Case("gt", AArch64CC::GT)
2231 .Case("le", AArch64CC::LE)
2232 .Case("al", AArch64CC::AL)
2233 .Case("nv", AArch64CC::NV)
2234 .Default(AArch64CC::Invalid);
2235 return CC;
2236}
2237
2238/// parseCondCode - Parse a Condition Code operand.
2239bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2240 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002241 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002242 SMLoc S = getLoc();
2243 const AsmToken &Tok = Parser.getTok();
2244 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2245
2246 StringRef Cond = Tok.getString();
2247 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2248 if (CC == AArch64CC::Invalid)
2249 return TokError("invalid condition code");
2250 Parser.Lex(); // Eat identifier token.
2251
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002252 if (invertCondCode) {
2253 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2254 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002255 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002256 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002257
2258 Operands.push_back(
2259 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2260 return false;
2261}
2262
2263/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2264/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002265OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002266AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002267 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002268 const AsmToken &Tok = Parser.getTok();
2269 std::string LowerID = Tok.getString().lower();
2270 AArch64_AM::ShiftExtendType ShOp =
2271 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2272 .Case("lsl", AArch64_AM::LSL)
2273 .Case("lsr", AArch64_AM::LSR)
2274 .Case("asr", AArch64_AM::ASR)
2275 .Case("ror", AArch64_AM::ROR)
2276 .Case("msl", AArch64_AM::MSL)
2277 .Case("uxtb", AArch64_AM::UXTB)
2278 .Case("uxth", AArch64_AM::UXTH)
2279 .Case("uxtw", AArch64_AM::UXTW)
2280 .Case("uxtx", AArch64_AM::UXTX)
2281 .Case("sxtb", AArch64_AM::SXTB)
2282 .Case("sxth", AArch64_AM::SXTH)
2283 .Case("sxtw", AArch64_AM::SXTW)
2284 .Case("sxtx", AArch64_AM::SXTX)
2285 .Default(AArch64_AM::InvalidShiftExtend);
2286
2287 if (ShOp == AArch64_AM::InvalidShiftExtend)
2288 return MatchOperand_NoMatch;
2289
2290 SMLoc S = Tok.getLoc();
2291 Parser.Lex();
2292
Nirav Davee833c6c2016-11-08 18:31:04 +00002293 bool Hash = parseOptionalToken(AsmToken::Hash);
2294
Tim Northover3b0846e2014-05-24 12:50:23 +00002295 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2296 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2297 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2298 ShOp == AArch64_AM::MSL) {
2299 // We expect a number here.
2300 TokError("expected #imm after shift specifier");
2301 return MatchOperand_ParseFail;
2302 }
2303
Chad Rosier2ff37b82016-12-27 16:58:09 +00002304 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002305 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2306 Operands.push_back(
2307 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2308 return MatchOperand_Success;
2309 }
2310
Chad Rosier2ff37b82016-12-27 16:58:09 +00002311 // Make sure we do actually have a number, identifier or a parenthesized
2312 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002313 SMLoc E = Parser.getTok().getLoc();
2314 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002315 !Parser.getTok().is(AsmToken::LParen) &&
2316 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002317 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002318 return MatchOperand_ParseFail;
2319 }
2320
2321 const MCExpr *ImmVal;
2322 if (getParser().parseExpression(ImmVal))
2323 return MatchOperand_ParseFail;
2324
2325 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2326 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002327 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002328 return MatchOperand_ParseFail;
2329 }
2330
Jim Grosbach57fd2622014-09-23 22:16:02 +00002331 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002332 Operands.push_back(AArch64Operand::CreateShiftExtend(
2333 ShOp, MCE->getValue(), true, S, E, getContext()));
2334 return MatchOperand_Success;
2335}
2336
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002337static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2338 if (FBS[AArch64::HasV8_1aOps])
2339 Str += "ARMv8.1a";
2340 else if (FBS[AArch64::HasV8_2aOps])
2341 Str += "ARMv8.2a";
2342 else
2343 Str += "(unknown)";
2344}
2345
2346void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2347 SMLoc S) {
2348 const uint16_t Op2 = Encoding & 7;
2349 const uint16_t Cm = (Encoding & 0x78) >> 3;
2350 const uint16_t Cn = (Encoding & 0x780) >> 7;
2351 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2352
2353 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2354
2355 Operands.push_back(
2356 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2357 Operands.push_back(
2358 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2359 Operands.push_back(
2360 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2361 Expr = MCConstantExpr::create(Op2, getContext());
2362 Operands.push_back(
2363 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2364}
2365
Tim Northover3b0846e2014-05-24 12:50:23 +00002366/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2367/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2368bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2369 OperandVector &Operands) {
2370 if (Name.find('.') != StringRef::npos)
2371 return TokError("invalid operand");
2372
2373 Mnemonic = Name;
2374 Operands.push_back(
2375 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2376
Rafael Espindola961d4692014-11-11 05:18:41 +00002377 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002378 const AsmToken &Tok = Parser.getTok();
2379 StringRef Op = Tok.getString();
2380 SMLoc S = Tok.getLoc();
2381
Tim Northover3b0846e2014-05-24 12:50:23 +00002382 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002383 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2384 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002385 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002386 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2387 std::string Str("IC " + std::string(IC->Name) + " requires ");
2388 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2389 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002390 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002391 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002392 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002393 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2394 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002395 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002396 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2397 std::string Str("DC " + std::string(DC->Name) + " requires ");
2398 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2399 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002400 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002401 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002402 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002403 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2404 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002405 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002406 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2407 std::string Str("AT " + std::string(AT->Name) + " requires ");
2408 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2409 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002410 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002411 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002412 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002413 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2414 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002415 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002416 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2417 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2418 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2419 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002420 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002421 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002422 }
2423
Tim Northover3b0846e2014-05-24 12:50:23 +00002424 Parser.Lex(); // Eat operand.
2425
2426 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2427 bool HasRegister = false;
2428
2429 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002430 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002431 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2432 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002433 HasRegister = true;
2434 }
2435
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002436 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002437 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002438 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002439 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002440
Nirav Davee833c6c2016-11-08 18:31:04 +00002441 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2442 return true;
2443
Tim Northover3b0846e2014-05-24 12:50:23 +00002444 return false;
2445}
2446
Alex Bradbury58eba092016-11-01 16:32:05 +00002447OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002448AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002449 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002450 const AsmToken &Tok = Parser.getTok();
2451
2452 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002453 if (parseOptionalToken(AsmToken::Hash) ||
2454 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002455 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002456 const MCExpr *ImmVal;
2457 SMLoc ExprLoc = getLoc();
2458 if (getParser().parseExpression(ImmVal))
2459 return MatchOperand_ParseFail;
2460 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2461 if (!MCE) {
2462 Error(ExprLoc, "immediate value expected for barrier operand");
2463 return MatchOperand_ParseFail;
2464 }
2465 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2466 Error(ExprLoc, "barrier operand out of range");
2467 return MatchOperand_ParseFail;
2468 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002469 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2470 Operands.push_back(AArch64Operand::CreateBarrier(
2471 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002472 return MatchOperand_Success;
2473 }
2474
2475 if (Tok.isNot(AsmToken::Identifier)) {
2476 TokError("invalid operand for instruction");
2477 return MatchOperand_ParseFail;
2478 }
2479
Tim Northovere6ae6762016-07-05 21:23:04 +00002480 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2481 if (!DB) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002482 TokError("invalid barrier option name");
2483 return MatchOperand_ParseFail;
2484 }
2485
2486 // The only valid named option for ISB is 'sy'
Tim Northovere6ae6762016-07-05 21:23:04 +00002487 if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002488 TokError("'sy' or #imm operand expected");
2489 return MatchOperand_ParseFail;
2490 }
2491
Tim Northovere6ae6762016-07-05 21:23:04 +00002492 Operands.push_back(AArch64Operand::CreateBarrier(
2493 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002494 Parser.Lex(); // Consume the option
2495
2496 return MatchOperand_Success;
2497}
2498
Alex Bradbury58eba092016-11-01 16:32:05 +00002499OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002500AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002501 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002502 const AsmToken &Tok = Parser.getTok();
2503
2504 if (Tok.isNot(AsmToken::Identifier))
2505 return MatchOperand_NoMatch;
2506
Tim Northovere6ae6762016-07-05 21:23:04 +00002507 int MRSReg, MSRReg;
2508 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2509 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2510 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2511 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2512 } else
2513 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002514
Tim Northovere6ae6762016-07-05 21:23:04 +00002515 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2516 unsigned PStateImm = -1;
2517 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2518 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002519
Tim Northovere6ae6762016-07-05 21:23:04 +00002520 Operands.push_back(
2521 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2522 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002523 Parser.Lex(); // Eat identifier
2524
2525 return MatchOperand_Success;
2526}
2527
2528/// tryParseVectorRegister - Parse a vector register operand.
2529bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002530 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002531 if (Parser.getTok().isNot(AsmToken::Identifier))
2532 return true;
2533
2534 SMLoc S = getLoc();
2535 // Check for a vector register specifier first.
2536 StringRef Kind;
2537 int64_t Reg = tryMatchVectorRegister(Kind, false);
2538 if (Reg == -1)
2539 return true;
2540 Operands.push_back(
2541 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2542 // If there was an explicit qualifier, that goes on as a literal text
2543 // operand.
2544 if (!Kind.empty())
2545 Operands.push_back(
2546 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2547
2548 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002549 SMLoc SIdx = getLoc();
2550 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002551 const MCExpr *ImmVal;
2552 if (getParser().parseExpression(ImmVal))
2553 return false;
2554 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2555 if (!MCE) {
2556 TokError("immediate value expected for vector index");
2557 return false;
2558 }
2559
2560 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002561
Nirav Davee833c6c2016-11-08 18:31:04 +00002562 if (parseToken(AsmToken::RBrac, "']' expected"))
2563 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002564
2565 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2566 E, getContext()));
2567 }
2568
2569 return false;
2570}
2571
2572/// parseRegister - Parse a non-vector register operand.
2573bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2574 SMLoc S = getLoc();
2575 // Try for a vector register.
2576 if (!tryParseVectorRegister(Operands))
2577 return false;
2578
2579 // Try for a scalar register.
2580 int64_t Reg = tryParseRegister();
2581 if (Reg == -1)
2582 return true;
2583 Operands.push_back(
2584 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2585
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 return false;
2587}
2588
2589bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002590 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002591 bool HasELFModifier = false;
2592 AArch64MCExpr::VariantKind RefKind;
2593
Nirav Davee833c6c2016-11-08 18:31:04 +00002594 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002595 HasELFModifier = true;
2596
Nirav Davee833c6c2016-11-08 18:31:04 +00002597 if (Parser.getTok().isNot(AsmToken::Identifier))
2598 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002599
2600 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2601 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2602 .Case("lo12", AArch64MCExpr::VK_LO12)
2603 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2604 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2605 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2606 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2607 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2608 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2609 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2610 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2611 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2612 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2613 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2614 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2615 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2616 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2617 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2618 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2619 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2620 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2621 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2622 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2623 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2624 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2625 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2626 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2627 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2628 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2629 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2630 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2631 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2632 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2633 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2634 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2635 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2636 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2637 .Default(AArch64MCExpr::VK_INVALID);
2638
Nirav Davee833c6c2016-11-08 18:31:04 +00002639 if (RefKind == AArch64MCExpr::VK_INVALID)
2640 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002641
2642 Parser.Lex(); // Eat identifier
2643
Nirav Davee833c6c2016-11-08 18:31:04 +00002644 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002645 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002646 }
2647
2648 if (getParser().parseExpression(ImmVal))
2649 return true;
2650
2651 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002652 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002653
2654 return false;
2655}
2656
2657/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2658bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002659 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002660 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2661 SMLoc S = getLoc();
2662 Parser.Lex(); // Eat left bracket token.
2663 StringRef Kind;
2664 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2665 if (FirstReg == -1)
2666 return true;
2667 int64_t PrevReg = FirstReg;
2668 unsigned Count = 1;
2669
Nirav Davee833c6c2016-11-08 18:31:04 +00002670 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 SMLoc Loc = getLoc();
2672 StringRef NextKind;
2673 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2674 if (Reg == -1)
2675 return true;
2676 // Any Kind suffices must match on all regs in the list.
2677 if (Kind != NextKind)
2678 return Error(Loc, "mismatched register size suffix");
2679
2680 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2681
2682 if (Space == 0 || Space > 3) {
2683 return Error(Loc, "invalid number of vectors");
2684 }
2685
2686 Count += Space;
2687 }
2688 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002689 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002690 SMLoc Loc = getLoc();
2691 StringRef NextKind;
2692 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2693 if (Reg == -1)
2694 return true;
2695 // Any Kind suffices must match on all regs in the list.
2696 if (Kind != NextKind)
2697 return Error(Loc, "mismatched register size suffix");
2698
2699 // Registers must be incremental (with wraparound at 31)
2700 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2701 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2702 return Error(Loc, "registers must be sequential");
2703
2704 PrevReg = Reg;
2705 ++Count;
2706 }
2707 }
2708
Nirav Davee833c6c2016-11-08 18:31:04 +00002709 if (parseToken(AsmToken::RCurly, "'}' expected"))
2710 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002711
2712 if (Count > 4)
2713 return Error(S, "invalid number of vectors");
2714
2715 unsigned NumElements = 0;
2716 char ElementKind = 0;
2717 if (!Kind.empty())
2718 parseValidVectorKind(Kind, NumElements, ElementKind);
2719
2720 Operands.push_back(AArch64Operand::CreateVectorList(
2721 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2722
2723 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002724 SMLoc SIdx = getLoc();
2725 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002726 const MCExpr *ImmVal;
2727 if (getParser().parseExpression(ImmVal))
2728 return false;
2729 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2730 if (!MCE) {
2731 TokError("immediate value expected for vector index");
2732 return false;
2733 }
2734
2735 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002736 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002737 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002738
2739 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2740 E, getContext()));
2741 }
2742 return false;
2743}
2744
Alex Bradbury58eba092016-11-01 16:32:05 +00002745OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002746AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002747 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002748 const AsmToken &Tok = Parser.getTok();
2749 if (!Tok.is(AsmToken::Identifier))
2750 return MatchOperand_NoMatch;
2751
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002752 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00002753
2754 MCContext &Ctx = getContext();
2755 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2756 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2757 return MatchOperand_NoMatch;
2758
2759 SMLoc S = getLoc();
2760 Parser.Lex(); // Eat register
2761
Nirav Davee833c6c2016-11-08 18:31:04 +00002762 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002763 Operands.push_back(
2764 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2765 return MatchOperand_Success;
2766 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002767
Nirav Davee833c6c2016-11-08 18:31:04 +00002768 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002769
2770 if (Parser.getTok().isNot(AsmToken::Integer)) {
2771 Error(getLoc(), "index must be absent or #0");
2772 return MatchOperand_ParseFail;
2773 }
2774
2775 const MCExpr *ImmVal;
2776 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2777 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2778 Error(getLoc(), "index must be absent or #0");
2779 return MatchOperand_ParseFail;
2780 }
2781
2782 Operands.push_back(
2783 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2784 return MatchOperand_Success;
2785}
2786
2787/// parseOperand - Parse a arm instruction operand. For now this parses the
2788/// operand regardless of the mnemonic.
2789bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
2790 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002791 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002792 // Check if the current operand has a custom associated parser, if so, try to
2793 // custom parse the operand, or fallback to the general approach.
2794 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2795 if (ResTy == MatchOperand_Success)
2796 return false;
2797 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2798 // there was a match, but an error occurred, in which case, just return that
2799 // the operand parsing failed.
2800 if (ResTy == MatchOperand_ParseFail)
2801 return true;
2802
2803 // Nothing custom, so do general case parsing.
2804 SMLoc S, E;
2805 switch (getLexer().getKind()) {
2806 default: {
2807 SMLoc S = getLoc();
2808 const MCExpr *Expr;
2809 if (parseSymbolicImmVal(Expr))
2810 return Error(S, "invalid operand");
2811
2812 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2813 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2814 return false;
2815 }
2816 case AsmToken::LBrac: {
2817 SMLoc Loc = Parser.getTok().getLoc();
2818 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
2819 getContext()));
2820 Parser.Lex(); // Eat '['
2821
2822 // There's no comma after a '[', so we can parse the next operand
2823 // immediately.
2824 return parseOperand(Operands, false, false);
2825 }
2826 case AsmToken::LCurly:
2827 return parseVectorList(Operands);
2828 case AsmToken::Identifier: {
2829 // If we're expecting a Condition Code operand, then just parse that.
2830 if (isCondCode)
2831 return parseCondCode(Operands, invertCondCode);
2832
2833 // If it's a register name, parse it.
2834 if (!parseRegister(Operands))
2835 return false;
2836
2837 // This could be an optional "shift" or "extend" operand.
2838 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
2839 // We can only continue if no tokens were eaten.
2840 if (GotShift != MatchOperand_NoMatch)
2841 return GotShift;
2842
2843 // This was not a register so parse other operands that start with an
2844 // identifier (like labels) as expressions and create them as immediates.
2845 const MCExpr *IdVal;
2846 S = getLoc();
2847 if (getParser().parseExpression(IdVal))
2848 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002849 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2850 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
2851 return false;
2852 }
2853 case AsmToken::Integer:
2854 case AsmToken::Real:
2855 case AsmToken::Hash: {
2856 // #42 -> immediate.
2857 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002858
2859 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002860
2861 // Parse a negative sign
2862 bool isNegative = false;
2863 if (Parser.getTok().is(AsmToken::Minus)) {
2864 isNegative = true;
2865 // We need to consume this token only when we have a Real, otherwise
2866 // we let parseSymbolicImmVal take care of it
2867 if (Parser.getLexer().peekTok().is(AsmToken::Real))
2868 Parser.Lex();
2869 }
2870
2871 // The only Real that should come through here is a literal #0.0 for
2872 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
2873 // so convert the value.
2874 const AsmToken &Tok = Parser.getTok();
2875 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002876 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002877 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2878 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
2879 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
2880 Mnemonic != "fcmlt")
2881 return TokError("unexpected floating point literal");
2882 else if (IntVal != 0 || isNegative)
2883 return TokError("expected floating-point constant #0.0");
2884 Parser.Lex(); // Eat the token.
2885
2886 Operands.push_back(
2887 AArch64Operand::CreateToken("#0", false, S, getContext()));
2888 Operands.push_back(
2889 AArch64Operand::CreateToken(".0", false, S, getContext()));
2890 return false;
2891 }
2892
2893 const MCExpr *ImmVal;
2894 if (parseSymbolicImmVal(ImmVal))
2895 return true;
2896
2897 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2898 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
2899 return false;
2900 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002901 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00002902 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002903 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00002904 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002905 Parser.Lex(); // Eat '='
2906 const MCExpr *SubExprVal;
2907 if (getParser().parseExpression(SubExprVal))
2908 return true;
2909
David Peixottoae5ba762014-07-18 16:05:14 +00002910 if (Operands.size() < 2 ||
2911 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00002912 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00002913
2914 bool IsXReg =
2915 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
2916 Operands[1]->getReg());
2917
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002918 MCContext& Ctx = getContext();
2919 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
2920 // 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 +00002921 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002922 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
2923 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
2924 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
2925 ShiftAmt += 16;
2926 Imm >>= 16;
2927 }
2928 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
2929 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
2930 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00002931 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002932 if (ShiftAmt)
2933 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
2934 ShiftAmt, true, S, E, Ctx));
2935 return false;
2936 }
David Peixottoae5ba762014-07-18 16:05:14 +00002937 APInt Simm = APInt(64, Imm << ShiftAmt);
2938 // check if the immediate is an unsigned or signed 32-bit int for W regs
2939 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
2940 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002941 }
2942 // 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 +00002943 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00002944 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002945 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
2946 return false;
2947 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002948 }
2949}
2950
2951/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
2952/// operands.
2953bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
2954 StringRef Name, SMLoc NameLoc,
2955 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002956 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002957 Name = StringSwitch<StringRef>(Name.lower())
2958 .Case("beq", "b.eq")
2959 .Case("bne", "b.ne")
2960 .Case("bhs", "b.hs")
2961 .Case("bcs", "b.cs")
2962 .Case("blo", "b.lo")
2963 .Case("bcc", "b.cc")
2964 .Case("bmi", "b.mi")
2965 .Case("bpl", "b.pl")
2966 .Case("bvs", "b.vs")
2967 .Case("bvc", "b.vc")
2968 .Case("bhi", "b.hi")
2969 .Case("bls", "b.ls")
2970 .Case("bge", "b.ge")
2971 .Case("blt", "b.lt")
2972 .Case("bgt", "b.gt")
2973 .Case("ble", "b.le")
2974 .Case("bal", "b.al")
2975 .Case("bnv", "b.nv")
2976 .Default(Name);
2977
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002978 // First check for the AArch64-specific .req directive.
2979 if (Parser.getTok().is(AsmToken::Identifier) &&
2980 Parser.getTok().getIdentifier() == ".req") {
2981 parseDirectiveReq(Name, NameLoc);
2982 // We always return 'error' for this, as we're done with this
2983 // statement and don't need to match the 'instruction."
2984 return true;
2985 }
2986
Tim Northover3b0846e2014-05-24 12:50:23 +00002987 // Create the leading tokens for the mnemonic, split by '.' characters.
2988 size_t Start = 0, Next = Name.find('.');
2989 StringRef Head = Name.slice(Start, Next);
2990
2991 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00002992 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
2993 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00002994
2995 Operands.push_back(
2996 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
2997 Mnemonic = Head;
2998
2999 // Handle condition codes for a branch mnemonic
3000 if (Head == "b" && Next != StringRef::npos) {
3001 Start = Next;
3002 Next = Name.find('.', Start + 1);
3003 Head = Name.slice(Start + 1, Next);
3004
3005 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3006 (Head.data() - Name.data()));
3007 AArch64CC::CondCode CC = parseCondCodeString(Head);
3008 if (CC == AArch64CC::Invalid)
3009 return Error(SuffixLoc, "invalid condition code");
3010 Operands.push_back(
3011 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3012 Operands.push_back(
3013 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3014 }
3015
3016 // Add the remaining tokens in the mnemonic.
3017 while (Next != StringRef::npos) {
3018 Start = Next;
3019 Next = Name.find('.', Start + 1);
3020 Head = Name.slice(Start, Next);
3021 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3022 (Head.data() - Name.data()) + 1);
3023 Operands.push_back(
3024 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3025 }
3026
3027 // Conditional compare instructions have a Condition Code operand, which needs
3028 // to be parsed and an immediate operand created.
3029 bool condCodeFourthOperand =
3030 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3031 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3032 Head == "csinc" || Head == "csinv" || Head == "csneg");
3033
3034 // These instructions are aliases to some of the conditional select
3035 // instructions. However, the condition code is inverted in the aliased
3036 // instruction.
3037 //
3038 // FIXME: Is this the correct way to handle these? Or should the parser
3039 // generate the aliased instructions directly?
3040 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3041 bool condCodeThirdOperand =
3042 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3043
3044 // Read the remaining operands.
3045 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3046 // Read the first operand.
3047 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003048 return true;
3049 }
3050
3051 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003052 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003053 // Parse and remember the operand.
3054 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3055 (N == 3 && condCodeThirdOperand) ||
3056 (N == 2 && condCodeSecondOperand),
3057 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003058 return true;
3059 }
3060
3061 // After successfully parsing some operands there are two special cases to
3062 // consider (i.e. notional operands not separated by commas). Both are due
3063 // to memory specifiers:
3064 // + An RBrac will end an address for load/store/prefetch
3065 // + An '!' will indicate a pre-indexed operation.
3066 //
3067 // It's someone else's responsibility to make sure these tokens are sane
3068 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003069
Nirav Davee833c6c2016-11-08 18:31:04 +00003070 SMLoc RLoc = Parser.getTok().getLoc();
3071 if (parseOptionalToken(AsmToken::RBrac))
3072 Operands.push_back(
3073 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3074 SMLoc ELoc = Parser.getTok().getLoc();
3075 if (parseOptionalToken(AsmToken::Exclaim))
3076 Operands.push_back(
3077 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003078
3079 ++N;
3080 }
3081 }
3082
Nirav Davee833c6c2016-11-08 18:31:04 +00003083 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3084 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003085
Tim Northover3b0846e2014-05-24 12:50:23 +00003086 return false;
3087}
3088
3089// FIXME: This entire function is a giant hack to provide us with decent
3090// operand range validation/diagnostics until TableGen/MC can be extended
3091// to support autogeneration of this kind of validation.
3092bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3093 SmallVectorImpl<SMLoc> &Loc) {
3094 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3095 // Check for indexed addressing modes w/ the base register being the
3096 // same as a destination/source register or pair load where
3097 // the Rt == Rt2. All of those are undefined behaviour.
3098 switch (Inst.getOpcode()) {
3099 case AArch64::LDPSWpre:
3100 case AArch64::LDPWpost:
3101 case AArch64::LDPWpre:
3102 case AArch64::LDPXpost:
3103 case AArch64::LDPXpre: {
3104 unsigned Rt = Inst.getOperand(1).getReg();
3105 unsigned Rt2 = Inst.getOperand(2).getReg();
3106 unsigned Rn = Inst.getOperand(3).getReg();
3107 if (RI->isSubRegisterEq(Rn, Rt))
3108 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3109 "is also a destination");
3110 if (RI->isSubRegisterEq(Rn, Rt2))
3111 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3112 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003113 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003114 }
3115 case AArch64::LDPDi:
3116 case AArch64::LDPQi:
3117 case AArch64::LDPSi:
3118 case AArch64::LDPSWi:
3119 case AArch64::LDPWi:
3120 case AArch64::LDPXi: {
3121 unsigned Rt = Inst.getOperand(0).getReg();
3122 unsigned Rt2 = Inst.getOperand(1).getReg();
3123 if (Rt == Rt2)
3124 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3125 break;
3126 }
3127 case AArch64::LDPDpost:
3128 case AArch64::LDPDpre:
3129 case AArch64::LDPQpost:
3130 case AArch64::LDPQpre:
3131 case AArch64::LDPSpost:
3132 case AArch64::LDPSpre:
3133 case AArch64::LDPSWpost: {
3134 unsigned Rt = Inst.getOperand(1).getReg();
3135 unsigned Rt2 = Inst.getOperand(2).getReg();
3136 if (Rt == Rt2)
3137 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3138 break;
3139 }
3140 case AArch64::STPDpost:
3141 case AArch64::STPDpre:
3142 case AArch64::STPQpost:
3143 case AArch64::STPQpre:
3144 case AArch64::STPSpost:
3145 case AArch64::STPSpre:
3146 case AArch64::STPWpost:
3147 case AArch64::STPWpre:
3148 case AArch64::STPXpost:
3149 case AArch64::STPXpre: {
3150 unsigned Rt = Inst.getOperand(1).getReg();
3151 unsigned Rt2 = Inst.getOperand(2).getReg();
3152 unsigned Rn = Inst.getOperand(3).getReg();
3153 if (RI->isSubRegisterEq(Rn, Rt))
3154 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3155 "is also a source");
3156 if (RI->isSubRegisterEq(Rn, Rt2))
3157 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3158 "is also a source");
3159 break;
3160 }
3161 case AArch64::LDRBBpre:
3162 case AArch64::LDRBpre:
3163 case AArch64::LDRHHpre:
3164 case AArch64::LDRHpre:
3165 case AArch64::LDRSBWpre:
3166 case AArch64::LDRSBXpre:
3167 case AArch64::LDRSHWpre:
3168 case AArch64::LDRSHXpre:
3169 case AArch64::LDRSWpre:
3170 case AArch64::LDRWpre:
3171 case AArch64::LDRXpre:
3172 case AArch64::LDRBBpost:
3173 case AArch64::LDRBpost:
3174 case AArch64::LDRHHpost:
3175 case AArch64::LDRHpost:
3176 case AArch64::LDRSBWpost:
3177 case AArch64::LDRSBXpost:
3178 case AArch64::LDRSHWpost:
3179 case AArch64::LDRSHXpost:
3180 case AArch64::LDRSWpost:
3181 case AArch64::LDRWpost:
3182 case AArch64::LDRXpost: {
3183 unsigned Rt = Inst.getOperand(1).getReg();
3184 unsigned Rn = Inst.getOperand(2).getReg();
3185 if (RI->isSubRegisterEq(Rn, Rt))
3186 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3187 "is also a source");
3188 break;
3189 }
3190 case AArch64::STRBBpost:
3191 case AArch64::STRBpost:
3192 case AArch64::STRHHpost:
3193 case AArch64::STRHpost:
3194 case AArch64::STRWpost:
3195 case AArch64::STRXpost:
3196 case AArch64::STRBBpre:
3197 case AArch64::STRBpre:
3198 case AArch64::STRHHpre:
3199 case AArch64::STRHpre:
3200 case AArch64::STRWpre:
3201 case AArch64::STRXpre: {
3202 unsigned Rt = Inst.getOperand(1).getReg();
3203 unsigned Rn = Inst.getOperand(2).getReg();
3204 if (RI->isSubRegisterEq(Rn, Rt))
3205 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3206 "is also a source");
3207 break;
3208 }
3209 }
3210
3211 // Now check immediate ranges. Separate from the above as there is overlap
3212 // in the instructions being checked and this keeps the nested conditionals
3213 // to a minimum.
3214 switch (Inst.getOpcode()) {
3215 case AArch64::ADDSWri:
3216 case AArch64::ADDSXri:
3217 case AArch64::ADDWri:
3218 case AArch64::ADDXri:
3219 case AArch64::SUBSWri:
3220 case AArch64::SUBSXri:
3221 case AArch64::SUBWri:
3222 case AArch64::SUBXri: {
3223 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3224 // some slight duplication here.
3225 if (Inst.getOperand(2).isExpr()) {
3226 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3227 AArch64MCExpr::VariantKind ELFRefKind;
3228 MCSymbolRefExpr::VariantKind DarwinRefKind;
3229 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003230 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3231
3232 // Only allow these with ADDXri.
3233 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3234 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3235 Inst.getOpcode() == AArch64::ADDXri)
3236 return false;
3237
3238 // Only allow these with ADDXri/ADDWri
3239 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3240 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3241 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3242 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3243 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3244 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3245 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3246 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3247 (Inst.getOpcode() == AArch64::ADDXri ||
3248 Inst.getOpcode() == AArch64::ADDWri))
3249 return false;
3250
3251 // Don't allow symbol refs in the immediate field otherwise
3252 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3253 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3254 // 'cmp w0, 'borked')
3255 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003256 }
Diana Picusc93518d2016-10-11 09:17:47 +00003257 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003258 }
3259 return false;
3260 }
3261 default:
3262 return false;
3263 }
3264}
3265
3266bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3267 switch (ErrCode) {
3268 case Match_MissingFeature:
3269 return Error(Loc,
3270 "instruction requires a CPU feature not currently enabled");
3271 case Match_InvalidOperand:
3272 return Error(Loc, "invalid operand for instruction");
3273 case Match_InvalidSuffix:
3274 return Error(Loc, "invalid type suffix for instruction");
3275 case Match_InvalidCondCode:
3276 return Error(Loc, "expected AArch64 condition code");
3277 case Match_AddSubRegExtendSmall:
3278 return Error(Loc,
3279 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3280 case Match_AddSubRegExtendLarge:
3281 return Error(Loc,
3282 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3283 case Match_AddSubSecondSource:
3284 return Error(Loc,
3285 "expected compatible register, symbol or integer in range [0, 4095]");
3286 case Match_LogicalSecondSource:
3287 return Error(Loc, "expected compatible register or logical immediate");
3288 case Match_InvalidMovImm32Shift:
3289 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3290 case Match_InvalidMovImm64Shift:
3291 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3292 case Match_AddSubRegShift32:
3293 return Error(Loc,
3294 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3295 case Match_AddSubRegShift64:
3296 return Error(Loc,
3297 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3298 case Match_InvalidFPImm:
3299 return Error(Loc,
3300 "expected compatible register or floating-point constant");
3301 case Match_InvalidMemoryIndexedSImm9:
3302 return Error(Loc, "index must be an integer in range [-256, 255].");
3303 case Match_InvalidMemoryIndexed4SImm7:
3304 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3305 case Match_InvalidMemoryIndexed8SImm7:
3306 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3307 case Match_InvalidMemoryIndexed16SImm7:
3308 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3309 case Match_InvalidMemoryWExtend8:
3310 return Error(Loc,
3311 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3312 case Match_InvalidMemoryWExtend16:
3313 return Error(Loc,
3314 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3315 case Match_InvalidMemoryWExtend32:
3316 return Error(Loc,
3317 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3318 case Match_InvalidMemoryWExtend64:
3319 return Error(Loc,
3320 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3321 case Match_InvalidMemoryWExtend128:
3322 return Error(Loc,
3323 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3324 case Match_InvalidMemoryXExtend8:
3325 return Error(Loc,
3326 "expected 'lsl' or 'sxtx' with optional shift of #0");
3327 case Match_InvalidMemoryXExtend16:
3328 return Error(Loc,
3329 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3330 case Match_InvalidMemoryXExtend32:
3331 return Error(Loc,
3332 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3333 case Match_InvalidMemoryXExtend64:
3334 return Error(Loc,
3335 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3336 case Match_InvalidMemoryXExtend128:
3337 return Error(Loc,
3338 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3339 case Match_InvalidMemoryIndexed1:
3340 return Error(Loc, "index must be an integer in range [0, 4095].");
3341 case Match_InvalidMemoryIndexed2:
3342 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3343 case Match_InvalidMemoryIndexed4:
3344 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3345 case Match_InvalidMemoryIndexed8:
3346 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3347 case Match_InvalidMemoryIndexed16:
3348 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003349 case Match_InvalidImm0_1:
3350 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003351 case Match_InvalidImm0_7:
3352 return Error(Loc, "immediate must be an integer in range [0, 7].");
3353 case Match_InvalidImm0_15:
3354 return Error(Loc, "immediate must be an integer in range [0, 15].");
3355 case Match_InvalidImm0_31:
3356 return Error(Loc, "immediate must be an integer in range [0, 31].");
3357 case Match_InvalidImm0_63:
3358 return Error(Loc, "immediate must be an integer in range [0, 63].");
3359 case Match_InvalidImm0_127:
3360 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003361 case Match_InvalidImm0_255:
3362 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003363 case Match_InvalidImm0_65535:
3364 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3365 case Match_InvalidImm1_8:
3366 return Error(Loc, "immediate must be an integer in range [1, 8].");
3367 case Match_InvalidImm1_16:
3368 return Error(Loc, "immediate must be an integer in range [1, 16].");
3369 case Match_InvalidImm1_32:
3370 return Error(Loc, "immediate must be an integer in range [1, 32].");
3371 case Match_InvalidImm1_64:
3372 return Error(Loc, "immediate must be an integer in range [1, 64].");
3373 case Match_InvalidIndex1:
3374 return Error(Loc, "expected lane specifier '[1]'");
3375 case Match_InvalidIndexB:
3376 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3377 case Match_InvalidIndexH:
3378 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3379 case Match_InvalidIndexS:
3380 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3381 case Match_InvalidIndexD:
3382 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3383 case Match_InvalidLabel:
3384 return Error(Loc, "expected label or encodable integer pc offset");
3385 case Match_MRS:
3386 return Error(Loc, "expected readable system register");
3387 case Match_MSR:
3388 return Error(Loc, "expected writable system register or pstate");
3389 case Match_MnemonicFail:
3390 return Error(Loc, "unrecognized instruction mnemonic");
3391 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003392 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003393 }
3394}
3395
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003396static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003397
3398bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3399 OperandVector &Operands,
3400 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003401 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003402 bool MatchingInlineAsm) {
3403 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003404 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3405 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003406
David Blaikie960ea3f2014-06-08 16:18:35 +00003407 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003408 unsigned NumOperands = Operands.size();
3409
3410 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003411 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3412 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3413 if (Op2.isReg() && Op3.isImm()) {
3414 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003415 if (Op3CE) {
3416 uint64_t Op3Val = Op3CE->getValue();
3417 uint64_t NewOp3Val = 0;
3418 uint64_t NewOp4Val = 0;
3419 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003420 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003421 NewOp3Val = (32 - Op3Val) & 0x1f;
3422 NewOp4Val = 31 - Op3Val;
3423 } else {
3424 NewOp3Val = (64 - Op3Val) & 0x3f;
3425 NewOp4Val = 63 - Op3Val;
3426 }
3427
Jim Grosbach13760bd2015-05-30 01:25:56 +00003428 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3429 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003430
3431 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003432 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003433 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003434 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3435 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3436 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003437 }
3438 }
Tim Northover03b99f62015-04-30 18:28:58 +00003439 } else if (NumOperands == 4 && Tok == "bfc") {
3440 // FIXME: Horrible hack to handle BFC->BFM alias.
3441 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3442 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3443 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3444
3445 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3446 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3447 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3448
3449 if (LSBCE && WidthCE) {
3450 uint64_t LSB = LSBCE->getValue();
3451 uint64_t Width = WidthCE->getValue();
3452
3453 uint64_t RegWidth = 0;
3454 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3455 Op1.getReg()))
3456 RegWidth = 64;
3457 else
3458 RegWidth = 32;
3459
3460 if (LSB >= RegWidth)
3461 return Error(LSBOp.getStartLoc(),
3462 "expected integer in range [0, 31]");
3463 if (Width < 1 || Width > RegWidth)
3464 return Error(WidthOp.getStartLoc(),
3465 "expected integer in range [1, 32]");
3466
3467 uint64_t ImmR = 0;
3468 if (RegWidth == 32)
3469 ImmR = (32 - LSB) & 0x1f;
3470 else
3471 ImmR = (64 - LSB) & 0x3f;
3472
3473 uint64_t ImmS = Width - 1;
3474
3475 if (ImmR != 0 && ImmS >= ImmR)
3476 return Error(WidthOp.getStartLoc(),
3477 "requested insert overflows register");
3478
Jim Grosbach13760bd2015-05-30 01:25:56 +00003479 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3480 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003481 Operands[0] = AArch64Operand::CreateToken(
3482 "bfm", false, Op.getStartLoc(), getContext());
3483 Operands[2] = AArch64Operand::CreateReg(
3484 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3485 SMLoc(), getContext());
3486 Operands[3] = AArch64Operand::CreateImm(
3487 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3488 Operands.emplace_back(
3489 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3490 WidthOp.getEndLoc(), getContext()));
3491 }
3492 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003493 } else if (NumOperands == 5) {
3494 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3495 // UBFIZ -> UBFM aliases.
3496 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003497 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3498 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3499 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003500
David Blaikie960ea3f2014-06-08 16:18:35 +00003501 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3502 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3503 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003504
3505 if (Op3CE && Op4CE) {
3506 uint64_t Op3Val = Op3CE->getValue();
3507 uint64_t Op4Val = Op4CE->getValue();
3508
3509 uint64_t RegWidth = 0;
3510 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003511 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003512 RegWidth = 64;
3513 else
3514 RegWidth = 32;
3515
3516 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003517 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003518 "expected integer in range [0, 31]");
3519 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003520 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003521 "expected integer in range [1, 32]");
3522
3523 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003524 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003525 NewOp3Val = (32 - Op3Val) & 0x1f;
3526 else
3527 NewOp3Val = (64 - Op3Val) & 0x3f;
3528
3529 uint64_t NewOp4Val = Op4Val - 1;
3530
3531 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003532 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003533 "requested insert overflows register");
3534
3535 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003536 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003537 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003538 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003539 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003540 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003541 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003542 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003543 if (Tok == "bfi")
3544 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003545 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003546 else if (Tok == "sbfiz")
3547 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003548 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003549 else if (Tok == "ubfiz")
3550 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003551 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003552 else
3553 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003554 }
3555 }
3556
3557 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3558 // UBFX -> UBFM aliases.
3559 } else if (NumOperands == 5 &&
3560 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003561 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3562 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3563 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003564
David Blaikie960ea3f2014-06-08 16:18:35 +00003565 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3566 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3567 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003568
3569 if (Op3CE && Op4CE) {
3570 uint64_t Op3Val = Op3CE->getValue();
3571 uint64_t Op4Val = Op4CE->getValue();
3572
3573 uint64_t RegWidth = 0;
3574 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003575 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003576 RegWidth = 64;
3577 else
3578 RegWidth = 32;
3579
3580 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003581 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003582 "expected integer in range [0, 31]");
3583 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003584 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003585 "expected integer in range [1, 32]");
3586
3587 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3588
3589 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003590 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003591 "requested extract overflows register");
3592
3593 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003594 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003595 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003596 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003597 if (Tok == "bfxil")
3598 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003599 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003600 else if (Tok == "sbfx")
3601 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003602 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003603 else if (Tok == "ubfx")
3604 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003605 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003606 else
3607 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003608 }
3609 }
3610 }
3611 }
3612 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3613 // InstAlias can't quite handle this since the reg classes aren't
3614 // subclasses.
3615 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3616 // The source register can be Wn here, but the matcher expects a
3617 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003618 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3619 if (Op.isReg()) {
3620 unsigned Reg = getXRegFromWReg(Op.getReg());
3621 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3622 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003623 }
3624 }
3625 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3626 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003627 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3628 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003629 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003630 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003631 // The source register can be Wn here, but the matcher expects a
3632 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003633 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3634 if (Op.isReg()) {
3635 unsigned Reg = getXRegFromWReg(Op.getReg());
3636 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3637 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003638 }
3639 }
3640 }
3641 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3642 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003643 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3644 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003645 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003646 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003647 // The source register can be Wn here, but the matcher expects a
3648 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003649 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3650 if (Op.isReg()) {
3651 unsigned Reg = getWRegFromXReg(Op.getReg());
3652 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3653 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003654 }
3655 }
3656 }
3657
3658 // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
3659 if (NumOperands == 3 && Tok == "fmov") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003660 AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
3661 AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
3662 if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003663 unsigned zreg =
Oliver Stannardb25914e2015-11-27 13:04:48 +00003664 !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003665 RegOp.getReg())
Tim Northover3b0846e2014-05-24 12:50:23 +00003666 ? AArch64::WZR
3667 : AArch64::XZR;
David Blaikie960ea3f2014-06-08 16:18:35 +00003668 Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
3669 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003670 }
3671 }
3672
3673 MCInst Inst;
3674 // First try to match against the secondary set of tables containing the
3675 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3676 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003677 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003678
3679 // If that fails, try against the alternate table containing long-form NEON:
3680 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003681 if (MatchResult != Match_Success) {
3682 // But first, save the short-form match result: we can use it in case the
3683 // long-form match also fails.
3684 auto ShortFormNEONErrorInfo = ErrorInfo;
3685 auto ShortFormNEONMatchResult = MatchResult;
3686
Tim Northover3b0846e2014-05-24 12:50:23 +00003687 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003688 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003689
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003690 // Now, both matches failed, and the long-form match failed on the mnemonic
3691 // suffix token operand. The short-form match failure is probably more
3692 // relevant: use it instead.
3693 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003694 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003695 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3696 MatchResult = ShortFormNEONMatchResult;
3697 ErrorInfo = ShortFormNEONErrorInfo;
3698 }
3699 }
3700
Tim Northover3b0846e2014-05-24 12:50:23 +00003701 switch (MatchResult) {
3702 case Match_Success: {
3703 // Perform range checking and other semantic validations
3704 SmallVector<SMLoc, 8> OperandLocs;
3705 NumOperands = Operands.size();
3706 for (unsigned i = 1; i < NumOperands; ++i)
3707 OperandLocs.push_back(Operands[i]->getStartLoc());
3708 if (validateInstruction(Inst, OperandLocs))
3709 return true;
3710
3711 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003712 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003713 return false;
3714 }
3715 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003716 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003717 // Special case the error message for the very common case where only
3718 // a single subtarget feature is missing (neon, e.g.).
3719 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003720 uint64_t Mask = 1;
3721 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3722 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003723 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003724 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003725 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003726 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003727 }
3728 return Error(IDLoc, Msg);
3729 }
3730 case Match_MnemonicFail:
3731 return showMatchError(IDLoc, MatchResult);
3732 case Match_InvalidOperand: {
3733 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003734
Tim Northover26bb14e2014-08-18 11:49:42 +00003735 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003736 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003737 return Error(IDLoc, "too few operands for instruction",
3738 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003739
David Blaikie960ea3f2014-06-08 16:18:35 +00003740 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003741 if (ErrorLoc == SMLoc())
3742 ErrorLoc = IDLoc;
3743 }
3744 // If the match failed on a suffix token operand, tweak the diagnostic
3745 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003746 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
3747 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00003748 MatchResult = Match_InvalidSuffix;
3749
3750 return showMatchError(ErrorLoc, MatchResult);
3751 }
3752 case Match_InvalidMemoryIndexed1:
3753 case Match_InvalidMemoryIndexed2:
3754 case Match_InvalidMemoryIndexed4:
3755 case Match_InvalidMemoryIndexed8:
3756 case Match_InvalidMemoryIndexed16:
3757 case Match_InvalidCondCode:
3758 case Match_AddSubRegExtendSmall:
3759 case Match_AddSubRegExtendLarge:
3760 case Match_AddSubSecondSource:
3761 case Match_LogicalSecondSource:
3762 case Match_AddSubRegShift32:
3763 case Match_AddSubRegShift64:
3764 case Match_InvalidMovImm32Shift:
3765 case Match_InvalidMovImm64Shift:
3766 case Match_InvalidFPImm:
3767 case Match_InvalidMemoryWExtend8:
3768 case Match_InvalidMemoryWExtend16:
3769 case Match_InvalidMemoryWExtend32:
3770 case Match_InvalidMemoryWExtend64:
3771 case Match_InvalidMemoryWExtend128:
3772 case Match_InvalidMemoryXExtend8:
3773 case Match_InvalidMemoryXExtend16:
3774 case Match_InvalidMemoryXExtend32:
3775 case Match_InvalidMemoryXExtend64:
3776 case Match_InvalidMemoryXExtend128:
3777 case Match_InvalidMemoryIndexed4SImm7:
3778 case Match_InvalidMemoryIndexed8SImm7:
3779 case Match_InvalidMemoryIndexed16SImm7:
3780 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003781 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003782 case Match_InvalidImm0_7:
3783 case Match_InvalidImm0_15:
3784 case Match_InvalidImm0_31:
3785 case Match_InvalidImm0_63:
3786 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003787 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00003788 case Match_InvalidImm0_65535:
3789 case Match_InvalidImm1_8:
3790 case Match_InvalidImm1_16:
3791 case Match_InvalidImm1_32:
3792 case Match_InvalidImm1_64:
3793 case Match_InvalidIndex1:
3794 case Match_InvalidIndexB:
3795 case Match_InvalidIndexH:
3796 case Match_InvalidIndexS:
3797 case Match_InvalidIndexD:
3798 case Match_InvalidLabel:
3799 case Match_MSR:
3800 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00003801 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003802 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003803 // Any time we get here, there's nothing fancy to do. Just get the
3804 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00003805 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003806 if (ErrorLoc == SMLoc())
3807 ErrorLoc = IDLoc;
3808 return showMatchError(ErrorLoc, MatchResult);
3809 }
3810 }
3811
3812 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003813}
3814
3815/// ParseDirective parses the arm specific directives
3816bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00003817 const MCObjectFileInfo::Environment Format =
3818 getContext().getObjectFileInfo()->getObjectFileType();
3819 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
3820 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00003821
Tim Northover3b0846e2014-05-24 12:50:23 +00003822 StringRef IDVal = DirectiveID.getIdentifier();
3823 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003824 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00003825 parseDirectiveArch(Loc);
3826 else if (IDVal == ".cpu")
3827 parseDirectiveCPU(Loc);
3828 else if (IDVal == ".hword")
3829 parseDirectiveWord(2, Loc);
3830 else if (IDVal == ".word")
3831 parseDirectiveWord(4, Loc);
3832 else if (IDVal == ".xword")
3833 parseDirectiveWord(8, Loc);
3834 else if (IDVal == ".tlsdesccall")
3835 parseDirectiveTLSDescCall(Loc);
3836 else if (IDVal == ".ltorg" || IDVal == ".pool")
3837 parseDirectiveLtorg(Loc);
3838 else if (IDVal == ".unreq")
3839 parseDirectiveUnreq(Loc);
3840 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00003841 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00003842 parseDirectiveInst(Loc);
3843 else
3844 return true;
3845 } else if (IDVal == MCLOHDirectiveName())
3846 parseDirectiveLOH(IDVal, Loc);
3847 else
3848 return true;
3849 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003850}
3851
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003852static const struct {
3853 const char *Name;
3854 const FeatureBitset Features;
3855} ExtensionMap[] = {
3856 { "crc", {AArch64::FeatureCRC} },
3857 { "crypto", {AArch64::FeatureCrypto} },
3858 { "fp", {AArch64::FeatureFPARMv8} },
3859 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003860 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00003861 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003862
3863 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003864 { "pan", {} },
3865 { "lor", {} },
3866 { "rdma", {} },
3867 { "profile", {} },
3868};
3869
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003870/// parseDirectiveArch
3871/// ::= .arch token
3872bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
3873 SMLoc ArchLoc = getLoc();
3874
3875 StringRef Arch, ExtensionString;
3876 std::tie(Arch, ExtensionString) =
3877 getParser().parseStringToEndOfStatement().trim().split('+');
3878
3879 unsigned ID = AArch64::parseArch(Arch);
Nirav Davee833c6c2016-11-08 18:31:04 +00003880 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
3881 return Error(ArchLoc, "unknown arch name");
3882
3883 if (parseToken(AsmToken::EndOfStatement))
3884 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003885
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003886 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00003887 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003888 AArch64::getArchFeatures(ID, AArch64Features);
3889 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
3890 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003891
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003892 MCSubtargetInfo &STI = copySTI();
3893 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
3894 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
3895
3896 SmallVector<StringRef, 4> RequestedExtensions;
3897 if (!ExtensionString.empty())
3898 ExtensionString.split(RequestedExtensions, '+');
3899
3900 FeatureBitset Features = STI.getFeatureBits();
3901 for (auto Name : RequestedExtensions) {
3902 bool EnableFeature = true;
3903
3904 if (Name.startswith_lower("no")) {
3905 EnableFeature = false;
3906 Name = Name.substr(2);
3907 }
3908
3909 for (const auto &Extension : ExtensionMap) {
3910 if (Extension.Name != Name)
3911 continue;
3912
3913 if (Extension.Features.none())
3914 report_fatal_error("unsupported architectural extension: " + Name);
3915
3916 FeatureBitset ToggleFeatures = EnableFeature
3917 ? (~Features & Extension.Features)
3918 : ( Features & Extension.Features);
3919 uint64_t Features =
3920 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
3921 setAvailableFeatures(Features);
3922 break;
3923 }
3924 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003925 return false;
3926}
3927
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003928/// parseDirectiveCPU
3929/// ::= .cpu id
3930bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
3931 SMLoc CPULoc = getLoc();
3932
3933 StringRef CPU, ExtensionString;
3934 std::tie(CPU, ExtensionString) =
3935 getParser().parseStringToEndOfStatement().trim().split('+');
3936
Nirav Davee833c6c2016-11-08 18:31:04 +00003937 if (parseToken(AsmToken::EndOfStatement))
3938 return true;
3939
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003940 SmallVector<StringRef, 4> RequestedExtensions;
3941 if (!ExtensionString.empty())
3942 ExtensionString.split(RequestedExtensions, '+');
3943
3944 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
3945 // once that is tablegen'ed
3946 if (!getSTI().isCPUStringValid(CPU)) {
3947 Error(CPULoc, "unknown CPU name");
3948 return false;
3949 }
3950
3951 MCSubtargetInfo &STI = copySTI();
3952 STI.setDefaultFeatures(CPU, "");
3953
3954 FeatureBitset Features = STI.getFeatureBits();
3955 for (auto Name : RequestedExtensions) {
3956 bool EnableFeature = true;
3957
3958 if (Name.startswith_lower("no")) {
3959 EnableFeature = false;
3960 Name = Name.substr(2);
3961 }
3962
3963 for (const auto &Extension : ExtensionMap) {
3964 if (Extension.Name != Name)
3965 continue;
3966
3967 if (Extension.Features.none())
3968 report_fatal_error("unsupported architectural extension: " + Name);
3969
3970 FeatureBitset ToggleFeatures = EnableFeature
3971 ? (~Features & Extension.Features)
3972 : ( Features & Extension.Features);
3973 uint64_t Features =
3974 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
3975 setAvailableFeatures(Features);
3976
3977 break;
3978 }
3979 }
3980 return false;
3981}
3982
Tim Northover3b0846e2014-05-24 12:50:23 +00003983/// parseDirectiveWord
3984/// ::= .word [ expression (, expression)* ]
3985bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003986 auto parseOp = [&]() -> bool {
3987 const MCExpr *Value;
3988 if (getParser().parseExpression(Value))
3989 return true;
3990 getParser().getStreamer().EmitValue(Value, Size, L);
3991 return false;
3992 };
Tim Northover3b0846e2014-05-24 12:50:23 +00003993
Nirav Davee833c6c2016-11-08 18:31:04 +00003994 if (parseMany(parseOp))
3995 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003996 return false;
3997}
3998
Chad Rosierdcd2a302014-10-22 20:35:57 +00003999/// parseDirectiveInst
4000/// ::= .inst opcode [, ...]
4001bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004002 if (getLexer().is(AsmToken::EndOfStatement))
4003 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004004
Nirav Davee833c6c2016-11-08 18:31:04 +00004005 auto parseOp = [&]() -> bool {
4006 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004007 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004008 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4009 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004010 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004011 if (check(!Value, L, "expected constant expression"))
4012 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004013 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004014 return false;
4015 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004016
Nirav Davee833c6c2016-11-08 18:31:04 +00004017 if (parseMany(parseOp))
4018 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004019 return false;
4020}
4021
Tim Northover3b0846e2014-05-24 12:50:23 +00004022// parseDirectiveTLSDescCall:
4023// ::= .tlsdesccall symbol
4024bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4025 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004026 if (check(getParser().parseIdentifier(Name), L,
4027 "expected symbol after directive") ||
4028 parseToken(AsmToken::EndOfStatement))
4029 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004030
Jim Grosbach6f482002015-05-18 18:43:14 +00004031 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004032 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4033 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004034
4035 MCInst Inst;
4036 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004037 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004038
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004039 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004040 return false;
4041}
4042
4043/// ::= .loh <lohName | lohId> label1, ..., labelN
4044/// The number of arguments depends on the loh identifier.
4045bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004046 MCLOHType Kind;
4047 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4048 if (getParser().getTok().isNot(AsmToken::Integer))
4049 return TokError("expected an identifier or a number in directive");
4050 // We successfully get a numeric value for the identifier.
4051 // Check if it is valid.
4052 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004053 if (Id <= -1U && !isValidMCLOHType(Id))
4054 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004055 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004056 } else {
4057 StringRef Name = getTok().getIdentifier();
4058 // We successfully parse an identifier.
4059 // Check if it is a recognized one.
4060 int Id = MCLOHNameToId(Name);
4061
4062 if (Id == -1)
4063 return TokError("invalid identifier in directive");
4064 Kind = (MCLOHType)Id;
4065 }
4066 // Consume the identifier.
4067 Lex();
4068 // Get the number of arguments of this LOH.
4069 int NbArgs = MCLOHIdToNbArgs(Kind);
4070
4071 assert(NbArgs != -1 && "Invalid number of arguments");
4072
4073 SmallVector<MCSymbol *, 3> Args;
4074 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4075 StringRef Name;
4076 if (getParser().parseIdentifier(Name))
4077 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004078 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004079
4080 if (Idx + 1 == NbArgs)
4081 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004082 if (parseToken(AsmToken::Comma,
4083 "unexpected token in '" + Twine(IDVal) + "' directive"))
4084 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004085 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004086 if (parseToken(AsmToken::EndOfStatement,
4087 "unexpected token in '" + Twine(IDVal) + "' directive"))
4088 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004089
4090 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4091 return false;
4092}
4093
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004094/// parseDirectiveLtorg
4095/// ::= .ltorg | .pool
4096bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004097 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4098 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004099 getTargetStreamer().emitCurrentConstantPool();
4100 return false;
4101}
4102
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004103/// parseDirectiveReq
4104/// ::= name .req registername
4105bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004106 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004107 Parser.Lex(); // Eat the '.req' token.
4108 SMLoc SRegLoc = getLoc();
4109 unsigned RegNum = tryParseRegister();
4110 bool IsVector = false;
4111
4112 if (RegNum == static_cast<unsigned>(-1)) {
4113 StringRef Kind;
4114 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004115 if (!Kind.empty())
4116 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004117 IsVector = true;
4118 }
4119
Nirav Dave2364748a2016-09-16 18:30:20 +00004120 if (RegNum == static_cast<unsigned>(-1))
4121 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004122
4123 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004124 if (parseToken(AsmToken::EndOfStatement,
4125 "unexpected input in .req directive"))
4126 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004127
4128 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004129 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004130 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4131
Nirav Dave2364748a2016-09-16 18:30:20 +00004132 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004133}
4134
4135/// parseDirectiveUneq
4136/// ::= .unreq registername
4137bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004138 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004139 if (getTok().isNot(AsmToken::Identifier))
4140 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004141 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4142 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004143 if (parseToken(AsmToken::EndOfStatement))
4144 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004145 return false;
4146}
4147
Tim Northover3b0846e2014-05-24 12:50:23 +00004148bool
4149AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4150 AArch64MCExpr::VariantKind &ELFRefKind,
4151 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4152 int64_t &Addend) {
4153 ELFRefKind = AArch64MCExpr::VK_INVALID;
4154 DarwinRefKind = MCSymbolRefExpr::VK_None;
4155 Addend = 0;
4156
4157 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4158 ELFRefKind = AE->getKind();
4159 Expr = AE->getSubExpr();
4160 }
4161
4162 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4163 if (SE) {
4164 // It's a simple symbol reference with no addend.
4165 DarwinRefKind = SE->getKind();
4166 return true;
4167 }
4168
4169 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4170 if (!BE)
4171 return false;
4172
4173 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4174 if (!SE)
4175 return false;
4176 DarwinRefKind = SE->getKind();
4177
4178 if (BE->getOpcode() != MCBinaryExpr::Add &&
4179 BE->getOpcode() != MCBinaryExpr::Sub)
4180 return false;
4181
4182 // See if the addend is is a constant, otherwise there's more going
4183 // on here than we can deal with.
4184 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4185 if (!AddendExpr)
4186 return false;
4187
4188 Addend = AddendExpr->getValue();
4189 if (BE->getOpcode() == MCBinaryExpr::Sub)
4190 Addend = -Addend;
4191
4192 // It's some symbol reference + a constant addend, but really
4193 // shouldn't use both Darwin and ELF syntax.
4194 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4195 DarwinRefKind == MCSymbolRefExpr::VK_None;
4196}
4197
4198/// Force static initialization.
4199extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004200 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4201 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4202 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004203}
4204
4205#define GET_REGISTER_MATCHER
4206#define GET_SUBTARGET_FEATURE_NAME
4207#define GET_MATCHER_IMPLEMENTATION
4208#include "AArch64GenAsmMatcher.inc"
4209
4210// Define this matcher function after the auto-generated include so we
4211// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004212unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004213 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004214 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004215 // If the kind is a token for a literal immediate, check if our asm
4216 // operand matches. This is for InstAliases which have a fixed-value
4217 // immediate in the syntax.
4218 int64_t ExpectedVal;
4219 switch (Kind) {
4220 default:
4221 return Match_InvalidOperand;
4222 case MCK__35_0:
4223 ExpectedVal = 0;
4224 break;
4225 case MCK__35_1:
4226 ExpectedVal = 1;
4227 break;
4228 case MCK__35_12:
4229 ExpectedVal = 12;
4230 break;
4231 case MCK__35_16:
4232 ExpectedVal = 16;
4233 break;
4234 case MCK__35_2:
4235 ExpectedVal = 2;
4236 break;
4237 case MCK__35_24:
4238 ExpectedVal = 24;
4239 break;
4240 case MCK__35_3:
4241 ExpectedVal = 3;
4242 break;
4243 case MCK__35_32:
4244 ExpectedVal = 32;
4245 break;
4246 case MCK__35_4:
4247 ExpectedVal = 4;
4248 break;
4249 case MCK__35_48:
4250 ExpectedVal = 48;
4251 break;
4252 case MCK__35_6:
4253 ExpectedVal = 6;
4254 break;
4255 case MCK__35_64:
4256 ExpectedVal = 64;
4257 break;
4258 case MCK__35_8:
4259 ExpectedVal = 8;
4260 break;
4261 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004262 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004263 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004264 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004265 if (!CE)
4266 return Match_InvalidOperand;
4267 if (CE->getValue() == ExpectedVal)
4268 return Match_Success;
4269 return Match_InvalidOperand;
4270}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004271
Alex Bradbury58eba092016-11-01 16:32:05 +00004272OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004273AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4274
4275 SMLoc S = getLoc();
4276
4277 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4278 Error(S, "expected register");
4279 return MatchOperand_ParseFail;
4280 }
4281
4282 int FirstReg = tryParseRegister();
4283 if (FirstReg == -1) {
4284 return MatchOperand_ParseFail;
4285 }
4286 const MCRegisterClass &WRegClass =
4287 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4288 const MCRegisterClass &XRegClass =
4289 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4290
4291 bool isXReg = XRegClass.contains(FirstReg),
4292 isWReg = WRegClass.contains(FirstReg);
4293 if (!isXReg && !isWReg) {
4294 Error(S, "expected first even register of a "
4295 "consecutive same-size even/odd register pair");
4296 return MatchOperand_ParseFail;
4297 }
4298
4299 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4300 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4301
4302 if (FirstEncoding & 0x1) {
4303 Error(S, "expected first even register of a "
4304 "consecutive same-size even/odd register pair");
4305 return MatchOperand_ParseFail;
4306 }
4307
4308 SMLoc M = getLoc();
4309 if (getParser().getTok().isNot(AsmToken::Comma)) {
4310 Error(M, "expected comma");
4311 return MatchOperand_ParseFail;
4312 }
4313 // Eat the comma
4314 getParser().Lex();
4315
4316 SMLoc E = getLoc();
4317 int SecondReg = tryParseRegister();
4318 if (SecondReg ==-1) {
4319 return MatchOperand_ParseFail;
4320 }
4321
Eugene Zelenko049b0172017-01-06 00:30:53 +00004322 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004323 (isXReg && !XRegClass.contains(SecondReg)) ||
4324 (isWReg && !WRegClass.contains(SecondReg))) {
4325 Error(E,"expected second odd register of a "
4326 "consecutive same-size even/odd register pair");
4327 return MatchOperand_ParseFail;
4328 }
Joel Jones504bf332016-10-24 13:37:13 +00004329
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004330 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004331 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004332 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4333 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4334 } else {
4335 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4336 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4337 }
4338
4339 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4340 getContext()));
4341
4342 return MatchOperand_Success;
4343}