blob: 9f49e67ced4c00bc1217d067fd585f433fc39b42 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
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
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000089 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000090
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)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000142 : MCTargetAsmParser(Options, STI, MII) {
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 }
Sam Parker6d42de72017-08-11 13:14:00 +0000468 bool isSImm10s8() 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 >= -4096 && Val < 4089 && (Val & 7) == 0);
476 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000477 bool isSImm7s4() 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 >= -256 && Val <= 252 && (Val & 3) == 0);
485 }
486 bool isSImm7s8() 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 >= -512 && Val <= 504 && (Val & 7) == 0);
494 }
495 bool isSImm7s16() const {
496 if (!isImm())
497 return false;
498 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
499 if (!MCE)
500 return false;
501 int64_t Val = MCE->getValue();
502 return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
503 }
504
505 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
506 AArch64MCExpr::VariantKind ELFRefKind;
507 MCSymbolRefExpr::VariantKind DarwinRefKind;
508 int64_t Addend;
509 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
510 Addend)) {
511 // If we don't understand the expression, assume the best and
512 // let the fixup and relocation code deal with it.
513 return true;
514 }
515
516 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
517 ELFRefKind == AArch64MCExpr::VK_LO12 ||
518 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
519 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
520 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
521 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
522 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
523 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
524 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
525 // Note that we don't range-check the addend. It's adjusted modulo page
526 // size when converted, so there is no "out of range" condition when using
527 // @pageoff.
528 return Addend >= 0 && (Addend % Scale) == 0;
529 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
530 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
531 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
532 return Addend == 0;
533 }
534
535 return false;
536 }
537
538 template <int Scale> bool isUImm12Offset() const {
539 if (!isImm())
540 return false;
541
542 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
543 if (!MCE)
544 return isSymbolicUImm12Offset(getImm(), Scale);
545
546 int64_t Val = MCE->getValue();
547 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
548 }
549
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000550 template <int N, int M>
551 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000552 if (!isImm())
553 return false;
554 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
555 if (!MCE)
556 return false;
557 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000558 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000559 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000560
Tim Northover3b0846e2014-05-24 12:50:23 +0000561 bool isLogicalImm32() const {
562 if (!isImm())
563 return false;
564 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
565 if (!MCE)
566 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000567 int64_t Val = MCE->getValue();
568 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
569 return false;
570 Val &= 0xFFFFFFFF;
571 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000572 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000573
Tim Northover3b0846e2014-05-24 12:50:23 +0000574 bool isLogicalImm64() const {
575 if (!isImm())
576 return false;
577 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
578 if (!MCE)
579 return false;
580 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
581 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000582
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000583 bool isLogicalImm32Not() const {
584 if (!isImm())
585 return false;
586 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
587 if (!MCE)
588 return false;
589 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
590 return AArch64_AM::isLogicalImmediate(Val, 32);
591 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000592
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000593 bool isLogicalImm64Not() const {
594 if (!isImm())
595 return false;
596 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
597 if (!MCE)
598 return false;
599 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
600 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000601
Tim Northover3b0846e2014-05-24 12:50:23 +0000602 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000603
Tim Northover3b0846e2014-05-24 12:50:23 +0000604 bool isAddSubImm() const {
605 if (!isShiftedImm() && !isImm())
606 return false;
607
608 const MCExpr *Expr;
609
610 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
611 if (isShiftedImm()) {
612 unsigned Shift = ShiftedImm.ShiftAmount;
613 Expr = ShiftedImm.Val;
614 if (Shift != 0 && Shift != 12)
615 return false;
616 } else {
617 Expr = getImm();
618 }
619
620 AArch64MCExpr::VariantKind ELFRefKind;
621 MCSymbolRefExpr::VariantKind DarwinRefKind;
622 int64_t Addend;
623 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
624 DarwinRefKind, Addend)) {
625 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
626 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
627 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
628 || ELFRefKind == AArch64MCExpr::VK_LO12
629 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
630 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
631 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
632 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
633 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
634 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
635 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
636 }
637
Diana Picusc93518d2016-10-11 09:17:47 +0000638 // If it's a constant, it should be a real immediate in range:
639 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
640 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
641
642 // If it's an expression, we hope for the best and let the fixup/relocation
643 // code deal with it.
644 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000645 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000646
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000647 bool isAddSubImmNeg() const {
648 if (!isShiftedImm() && !isImm())
649 return false;
650
651 const MCExpr *Expr;
652
653 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
654 if (isShiftedImm()) {
655 unsigned Shift = ShiftedImm.ShiftAmount;
656 Expr = ShiftedImm.Val;
657 if (Shift != 0 && Shift != 12)
658 return false;
659 } else
660 Expr = getImm();
661
662 // Otherwise it should be a real negative immediate in range:
663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
664 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
665 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000666
Tim Northover3b0846e2014-05-24 12:50:23 +0000667 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000668
Tim Northover3b0846e2014-05-24 12:50:23 +0000669 bool isSIMDImmType10() const {
670 if (!isImm())
671 return false;
672 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
673 if (!MCE)
674 return false;
675 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
676 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000677
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000678 template<int N>
679 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000680 if (!isImm())
681 return false;
682 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
683 if (!MCE)
684 return true;
685 int64_t Val = MCE->getValue();
686 if (Val & 0x3)
687 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000688 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
689 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000690 }
691
692 bool
693 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
694 if (!isImm())
695 return false;
696
697 AArch64MCExpr::VariantKind ELFRefKind;
698 MCSymbolRefExpr::VariantKind DarwinRefKind;
699 int64_t Addend;
700 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
701 DarwinRefKind, Addend)) {
702 return false;
703 }
704 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
705 return false;
706
707 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
708 if (ELFRefKind == AllowedModifiers[i])
709 return Addend == 0;
710 }
711
712 return false;
713 }
714
715 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000716 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000717 }
718
719 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000720 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
721 AArch64MCExpr::VK_TPREL_G2,
722 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000723 }
724
725 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000726 return isMovWSymbol({
727 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000728 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
729 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000730 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 }
732
733 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000734 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
735 AArch64MCExpr::VK_TPREL_G0,
736 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000737 }
738
739 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000740 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000741 }
742
743 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000744 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000745 }
746
747 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000748 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
749 AArch64MCExpr::VK_TPREL_G1_NC,
750 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000751 }
752
753 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000754 return isMovWSymbol(
755 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
756 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000757 }
758
759 template<int RegWidth, int Shift>
760 bool isMOVZMovAlias() const {
761 if (!isImm()) return false;
762
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 uint64_t Value = CE->getValue();
766
Tim Northoverdaa1c012016-06-16 01:42:25 +0000767 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 }
769
770 template<int RegWidth, int Shift>
771 bool isMOVNMovAlias() const {
772 if (!isImm()) return false;
773
774 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
775 if (!CE) return false;
776 uint64_t Value = CE->getValue();
777
Tim Northoverdaa1c012016-06-16 01:42:25 +0000778 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000779 }
780
781 bool isFPImm() const { return Kind == k_FPImm; }
782 bool isBarrier() const { return Kind == k_Barrier; }
783 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000784
Tim Northover3b0846e2014-05-24 12:50:23 +0000785 bool isMRSSystemRegister() const {
786 if (!isSysReg()) return false;
787
Tim Northover7cd58932015-01-22 17:23:04 +0000788 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000789 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000790
Tim Northover3b0846e2014-05-24 12:50:23 +0000791 bool isMSRSystemRegister() const {
792 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000793 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000794 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000795
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000796 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000797 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000798 return (SysReg.PStateField == AArch64PState::PAN ||
799 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000800 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000801
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000802 bool isSystemPStateFieldWithImm0_15() const {
803 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000804 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000806
Tim Northover3b0846e2014-05-24 12:50:23 +0000807 bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
808 bool isVectorReg() const { return Kind == k_Register && Reg.isVector; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000809
Tim Northover3b0846e2014-05-24 12:50:23 +0000810 bool isVectorRegLo() const {
811 return Kind == k_Register && Reg.isVector &&
812 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
813 Reg.RegNum);
814 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000815
Tim Northover3b0846e2014-05-24 12:50:23 +0000816 bool isGPR32as64() const {
817 return Kind == k_Register && !Reg.isVector &&
818 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
819 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000820
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000821 bool isWSeqPair() const {
822 return Kind == k_Register && !Reg.isVector &&
823 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
824 Reg.RegNum);
825 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000826
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000827 bool isXSeqPair() const {
828 return Kind == k_Register && !Reg.isVector &&
829 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
830 Reg.RegNum);
831 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000832
833 bool isGPR64sp0() const {
834 return Kind == k_Register && !Reg.isVector &&
835 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
836 }
837
Sam Parker5f934642017-08-31 09:27:04 +0000838 template<int64_t Angle, int64_t Remainder>
839 bool isComplexRotation() const {
840 if (!isImm()) return false;
841
842 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
843 if (!CE) return false;
844 uint64_t Value = CE->getValue();
845
846 return (Value % Angle == Remainder && Value <= 270);
847 }
848
Tim Northover3b0846e2014-05-24 12:50:23 +0000849 /// Is this a vector list with the type implicit (presumably attached to the
850 /// instruction itself)?
851 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
852 return Kind == k_VectorList && VectorList.Count == NumRegs &&
853 !VectorList.ElementKind;
854 }
855
856 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
857 bool isTypedVectorList() const {
858 if (Kind != k_VectorList)
859 return false;
860 if (VectorList.Count != NumRegs)
861 return false;
862 if (VectorList.ElementKind != ElementKind)
863 return false;
864 return VectorList.NumElements == NumElements;
865 }
866
867 bool isVectorIndex1() const {
868 return Kind == k_VectorIndex && VectorIndex.Val == 1;
869 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000870
Tim Northover3b0846e2014-05-24 12:50:23 +0000871 bool isVectorIndexB() const {
872 return Kind == k_VectorIndex && VectorIndex.Val < 16;
873 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000874
Tim Northover3b0846e2014-05-24 12:50:23 +0000875 bool isVectorIndexH() const {
876 return Kind == k_VectorIndex && VectorIndex.Val < 8;
877 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000878
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 bool isVectorIndexS() const {
880 return Kind == k_VectorIndex && VectorIndex.Val < 4;
881 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000882
Tim Northover3b0846e2014-05-24 12:50:23 +0000883 bool isVectorIndexD() const {
884 return Kind == k_VectorIndex && VectorIndex.Val < 2;
885 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000886
Tim Northover3b0846e2014-05-24 12:50:23 +0000887 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000888
Tim Northover3b0846e2014-05-24 12:50:23 +0000889 bool isTokenEqual(StringRef Str) const {
890 return Kind == k_Token && getToken() == Str;
891 }
892 bool isSysCR() const { return Kind == k_SysCR; }
893 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000894 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000895 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
896 bool isShifter() const {
897 if (!isShiftExtend())
898 return false;
899
900 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
901 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
902 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
903 ST == AArch64_AM::MSL);
904 }
905 bool isExtend() const {
906 if (!isShiftExtend())
907 return false;
908
909 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
910 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
911 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
912 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
913 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
914 ET == AArch64_AM::LSL) &&
915 getShiftExtendAmount() <= 4;
916 }
917
918 bool isExtend64() const {
919 if (!isExtend())
920 return false;
921 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
922 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
923 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
924 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000925
Tim Northover3b0846e2014-05-24 12:50:23 +0000926 bool isExtendLSL64() const {
927 if (!isExtend())
928 return false;
929 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
930 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
931 ET == AArch64_AM::LSL) &&
932 getShiftExtendAmount() <= 4;
933 }
934
935 template<int Width> bool isMemXExtend() const {
936 if (!isExtend())
937 return false;
938 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
939 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
940 (getShiftExtendAmount() == Log2_32(Width / 8) ||
941 getShiftExtendAmount() == 0);
942 }
943
944 template<int Width> bool isMemWExtend() const {
945 if (!isExtend())
946 return false;
947 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
948 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
949 (getShiftExtendAmount() == Log2_32(Width / 8) ||
950 getShiftExtendAmount() == 0);
951 }
952
953 template <unsigned width>
954 bool isArithmeticShifter() const {
955 if (!isShifter())
956 return false;
957
958 // An arithmetic shifter is LSL, LSR, or ASR.
959 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
960 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
961 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
962 }
963
964 template <unsigned width>
965 bool isLogicalShifter() const {
966 if (!isShifter())
967 return false;
968
969 // A logical shifter is LSL, LSR, ASR or ROR.
970 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
971 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
972 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
973 getShiftExtendAmount() < width;
974 }
975
976 bool isMovImm32Shifter() const {
977 if (!isShifter())
978 return false;
979
980 // A MOVi shifter is LSL of 0, 16, 32, or 48.
981 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
982 if (ST != AArch64_AM::LSL)
983 return false;
984 uint64_t Val = getShiftExtendAmount();
985 return (Val == 0 || Val == 16);
986 }
987
988 bool isMovImm64Shifter() const {
989 if (!isShifter())
990 return false;
991
992 // A MOVi shifter is LSL of 0 or 16.
993 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
994 if (ST != AArch64_AM::LSL)
995 return false;
996 uint64_t Val = getShiftExtendAmount();
997 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
998 }
999
1000 bool isLogicalVecShifter() const {
1001 if (!isShifter())
1002 return false;
1003
1004 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1005 unsigned Shift = getShiftExtendAmount();
1006 return getShiftExtendType() == AArch64_AM::LSL &&
1007 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1008 }
1009
1010 bool isLogicalVecHalfWordShifter() const {
1011 if (!isLogicalVecShifter())
1012 return false;
1013
1014 // A logical vector shifter is a left shift by 0 or 8.
1015 unsigned Shift = getShiftExtendAmount();
1016 return getShiftExtendType() == AArch64_AM::LSL &&
1017 (Shift == 0 || Shift == 8);
1018 }
1019
1020 bool isMoveVecShifter() const {
1021 if (!isShiftExtend())
1022 return false;
1023
1024 // A logical vector shifter is a left shift by 8 or 16.
1025 unsigned Shift = getShiftExtendAmount();
1026 return getShiftExtendType() == AArch64_AM::MSL &&
1027 (Shift == 8 || Shift == 16);
1028 }
1029
1030 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1031 // to LDUR/STUR when the offset is not legal for the former but is for
1032 // the latter. As such, in addition to checking for being a legal unscaled
1033 // address, also check that it is not a legal scaled address. This avoids
1034 // ambiguity in the matcher.
1035 template<int Width>
1036 bool isSImm9OffsetFB() const {
1037 return isSImm9() && !isUImm12Offset<Width / 8>();
1038 }
1039
1040 bool isAdrpLabel() const {
1041 // Validation was handled during parsing, so we just sanity check that
1042 // something didn't go haywire.
1043 if (!isImm())
1044 return false;
1045
1046 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1047 int64_t Val = CE->getValue();
1048 int64_t Min = - (4096 * (1LL << (21 - 1)));
1049 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1050 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1051 }
1052
1053 return true;
1054 }
1055
1056 bool isAdrLabel() const {
1057 // Validation was handled during parsing, so we just sanity check that
1058 // something didn't go haywire.
1059 if (!isImm())
1060 return false;
1061
1062 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1063 int64_t Val = CE->getValue();
1064 int64_t Min = - (1LL << (21 - 1));
1065 int64_t Max = ((1LL << (21 - 1)) - 1);
1066 return Val >= Min && Val <= Max;
1067 }
1068
1069 return true;
1070 }
1071
1072 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1073 // Add as immediates when possible. Null MCExpr = 0.
1074 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001075 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001076 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001077 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001078 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001079 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001080 }
1081
1082 void addRegOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001084 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001085 }
1086
1087 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 assert(
1090 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1091
1092 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1093 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1094 RI->getEncodingValue(getReg()));
1095
Jim Grosbache9119e42015-05-13 18:37:00 +00001096 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001097 }
1098
1099 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1100 assert(N == 1 && "Invalid number of operands!");
1101 assert(
1102 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001103 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001104 }
1105
1106 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1107 assert(N == 1 && "Invalid number of operands!");
1108 assert(
1109 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001110 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001111 }
1112
1113 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1114 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001115 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001116 }
1117
1118 template <unsigned NumRegs>
1119 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1120 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001121 static const unsigned FirstRegs[] = { AArch64::D0,
1122 AArch64::D0_D1,
1123 AArch64::D0_D1_D2,
1124 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001125 unsigned FirstReg = FirstRegs[NumRegs - 1];
1126
1127 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001128 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001129 }
1130
1131 template <unsigned NumRegs>
1132 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001134 static const unsigned FirstRegs[] = { AArch64::Q0,
1135 AArch64::Q0_Q1,
1136 AArch64::Q0_Q1_Q2,
1137 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001138 unsigned FirstReg = FirstRegs[NumRegs - 1];
1139
1140 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001141 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001142 }
1143
1144 void addVectorIndex1Operands(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 addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1150 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001151 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001152 }
1153
1154 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1155 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001156 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001157 }
1158
1159 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1160 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001161 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001162 }
1163
1164 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001166 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001167 }
1168
1169 void addImmOperands(MCInst &Inst, unsigned N) const {
1170 assert(N == 1 && "Invalid number of operands!");
1171 // If this is a pageoff symrefexpr with an addend, adjust the addend
1172 // to be only the page-offset portion. Otherwise, just add the expr
1173 // as-is.
1174 addExpr(Inst, getImm());
1175 }
1176
1177 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1178 assert(N == 2 && "Invalid number of operands!");
1179 if (isShiftedImm()) {
1180 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001181 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 } else {
1183 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001184 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001185 }
1186 }
1187
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001188 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1189 assert(N == 2 && "Invalid number of operands!");
1190
1191 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1192 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1193 int64_t Val = -CE->getValue();
1194 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1195
1196 Inst.addOperand(MCOperand::createImm(Val));
1197 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1198 }
1199
Tim Northover3b0846e2014-05-24 12:50:23 +00001200 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1201 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001202 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001203 }
1204
1205 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1206 assert(N == 1 && "Invalid number of operands!");
1207 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1208 if (!MCE)
1209 addExpr(Inst, getImm());
1210 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001211 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001212 }
1213
1214 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1215 addImmOperands(Inst, N);
1216 }
1217
1218 template<int Scale>
1219 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 1 && "Invalid number of operands!");
1221 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1222
1223 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001224 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001225 return;
1226 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001227 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001228 }
1229
1230 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1231 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001232 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001233 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001234 }
1235
Sam Parker6d42de72017-08-11 13:14:00 +00001236 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1239 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1240 }
1241
Tim Northover3b0846e2014-05-24 12:50:23 +00001242 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1243 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001244 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001245 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001246 }
1247
1248 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1249 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001250 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001251 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001252 }
1253
1254 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001256 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001257 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001258 }
1259
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001260 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
1262 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1263 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1264 }
1265
Tim Northover3b0846e2014-05-24 12:50:23 +00001266 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001268 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001269 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001270 }
1271
1272 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001274 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001275 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001276 }
1277
1278 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1279 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001280 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001281 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001282 }
1283
1284 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1285 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001286 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001287 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001288 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001289 }
1290
1291 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1292 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001293 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001294 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001295 }
1296
1297 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001299 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001300 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001301 }
1302
1303 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1304 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001305 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001306 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001307 }
1308
1309 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001311 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001312 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 }
1314
1315 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001317 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001318 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001319 }
1320
1321 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1322 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001323 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001324 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001325 }
1326
1327 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1328 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001329 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 }
1332
1333 void addImm0_255Operands(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());
Jim Grosbache9119e42015-05-13 18:37:00 +00001336 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001337 }
1338
1339 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1340 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001341 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001342 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001343 }
1344
1345 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1346 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001347 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001348 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001349 }
1350
1351 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1352 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001353 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001354 uint64_t encoding =
1355 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001356 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001357 }
1358
1359 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1360 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001361 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001362 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001363 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001364 }
1365
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001366 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1367 assert(N == 1 && "Invalid number of operands!");
1368 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1369 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1370 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001371 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001372 }
1373
1374 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1375 assert(N == 1 && "Invalid number of operands!");
1376 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1377 uint64_t encoding =
1378 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001379 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001380 }
1381
Tim Northover3b0846e2014-05-24 12:50:23 +00001382 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1383 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001384 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001385 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001386 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001387 }
1388
1389 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1390 // Branch operands don't encode the low bits, so shift them off
1391 // here. If it's a label, however, just put it on directly as there's
1392 // not enough information now to do anything.
1393 assert(N == 1 && "Invalid number of operands!");
1394 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1395 if (!MCE) {
1396 addExpr(Inst, getImm());
1397 return;
1398 }
1399 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001400 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001401 }
1402
1403 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1404 // Branch operands don't encode the low bits, so shift them off
1405 // here. If it's a label, however, just put it on directly as there's
1406 // not enough information now to do anything.
1407 assert(N == 1 && "Invalid number of operands!");
1408 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1409 if (!MCE) {
1410 addExpr(Inst, getImm());
1411 return;
1412 }
1413 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001414 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001415 }
1416
1417 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1418 // Branch operands don't encode the low bits, so shift them off
1419 // here. If it's a label, however, just put it on directly as there's
1420 // not enough information now to do anything.
1421 assert(N == 1 && "Invalid number of operands!");
1422 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1423 if (!MCE) {
1424 addExpr(Inst, getImm());
1425 return;
1426 }
1427 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 }
1430
1431 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1432 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001438 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001439 }
1440
1441 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443
Jim Grosbache9119e42015-05-13 18:37:00 +00001444 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001445 }
1446
1447 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1448 assert(N == 1 && "Invalid number of operands!");
1449
Jim Grosbache9119e42015-05-13 18:37:00 +00001450 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001451 }
1452
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001453 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455
1456 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1457 }
1458
1459 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001460 assert(N == 1 && "Invalid number of operands!");
1461
Jim Grosbache9119e42015-05-13 18:37:00 +00001462 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001463 }
1464
1465 void addSysCROperands(MCInst &Inst, unsigned N) const {
1466 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001467 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001468 }
1469
1470 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001472 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001473 }
1474
Oliver Stannarda34e4702015-12-01 10:48:51 +00001475 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1478 }
1479
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 void addShifterOperands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
1482 unsigned Imm =
1483 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001484 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001485 }
1486
1487 void addExtendOperands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
1489 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1490 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1491 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001492 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001493 }
1494
1495 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1498 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1499 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001500 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001501 }
1502
1503 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
1505 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1506 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001507 Inst.addOperand(MCOperand::createImm(IsSigned));
1508 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001509 }
1510
1511 // For 8-bit load/store instructions with a register offset, both the
1512 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1513 // they're disambiguated by whether the shift was explicit or implicit rather
1514 // than its size.
1515 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1516 assert(N == 2 && "Invalid number of operands!");
1517 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1518 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001519 Inst.addOperand(MCOperand::createImm(IsSigned));
1520 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001521 }
1522
1523 template<int Shift>
1524 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526
1527 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1528 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001529 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 }
1531
1532 template<int Shift>
1533 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 1 && "Invalid number of operands!");
1535
1536 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1537 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001538 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001539 }
1540
Sam Parker5f934642017-08-31 09:27:04 +00001541 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1542 assert(N == 1 && "Invalid number of operands!");
1543 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1544 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1545 }
1546
1547 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 1 && "Invalid number of operands!");
1549 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1550 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1551 }
1552
Tim Northover3b0846e2014-05-24 12:50:23 +00001553 void print(raw_ostream &OS) const override;
1554
David Blaikie960ea3f2014-06-08 16:18:35 +00001555 static std::unique_ptr<AArch64Operand>
1556 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1557 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001558 Op->Tok.Data = Str.data();
1559 Op->Tok.Length = Str.size();
1560 Op->Tok.IsSuffix = IsSuffix;
1561 Op->StartLoc = S;
1562 Op->EndLoc = S;
1563 return Op;
1564 }
1565
David Blaikie960ea3f2014-06-08 16:18:35 +00001566 static std::unique_ptr<AArch64Operand>
1567 CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
1568 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001569 Op->Reg.RegNum = RegNum;
1570 Op->Reg.isVector = isVector;
1571 Op->StartLoc = S;
1572 Op->EndLoc = E;
1573 return Op;
1574 }
1575
David Blaikie960ea3f2014-06-08 16:18:35 +00001576 static std::unique_ptr<AArch64Operand>
1577 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1578 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1579 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001580 Op->VectorList.RegNum = RegNum;
1581 Op->VectorList.Count = Count;
1582 Op->VectorList.NumElements = NumElements;
1583 Op->VectorList.ElementKind = ElementKind;
1584 Op->StartLoc = S;
1585 Op->EndLoc = E;
1586 return Op;
1587 }
1588
David Blaikie960ea3f2014-06-08 16:18:35 +00001589 static std::unique_ptr<AArch64Operand>
1590 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1591 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001592 Op->VectorIndex.Val = Idx;
1593 Op->StartLoc = S;
1594 Op->EndLoc = E;
1595 return Op;
1596 }
1597
David Blaikie960ea3f2014-06-08 16:18:35 +00001598 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1599 SMLoc E, MCContext &Ctx) {
1600 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001601 Op->Imm.Val = Val;
1602 Op->StartLoc = S;
1603 Op->EndLoc = E;
1604 return Op;
1605 }
1606
David Blaikie960ea3f2014-06-08 16:18:35 +00001607 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1608 unsigned ShiftAmount,
1609 SMLoc S, SMLoc E,
1610 MCContext &Ctx) {
1611 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001612 Op->ShiftedImm .Val = Val;
1613 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1614 Op->StartLoc = S;
1615 Op->EndLoc = E;
1616 return Op;
1617 }
1618
David Blaikie960ea3f2014-06-08 16:18:35 +00001619 static std::unique_ptr<AArch64Operand>
1620 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1621 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001622 Op->CondCode.Code = Code;
1623 Op->StartLoc = S;
1624 Op->EndLoc = E;
1625 return Op;
1626 }
1627
David Blaikie960ea3f2014-06-08 16:18:35 +00001628 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1629 MCContext &Ctx) {
1630 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001631 Op->FPImm.Val = Val;
1632 Op->StartLoc = S;
1633 Op->EndLoc = S;
1634 return Op;
1635 }
1636
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001637 static std::unique_ptr<AArch64Operand> CreateBarrier(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_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001642 Op->Barrier.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
Tim Northover7cd58932015-01-22 17:23:04 +00001650 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1651 uint32_t MRSReg,
1652 uint32_t MSRReg,
1653 uint32_t PStateField,
1654 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001655 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001656 Op->SysReg.Data = Str.data();
1657 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001658 Op->SysReg.MRSReg = MRSReg;
1659 Op->SysReg.MSRReg = MSRReg;
1660 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001661 Op->StartLoc = S;
1662 Op->EndLoc = S;
1663 return Op;
1664 }
1665
David Blaikie960ea3f2014-06-08 16:18:35 +00001666 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1667 SMLoc E, MCContext &Ctx) {
1668 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001669 Op->SysCRImm.Val = Val;
1670 Op->StartLoc = S;
1671 Op->EndLoc = E;
1672 return Op;
1673 }
1674
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001675 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1676 StringRef Str,
1677 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001678 MCContext &Ctx) {
1679 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001680 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001681 Op->Barrier.Data = Str.data();
1682 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001683 Op->StartLoc = S;
1684 Op->EndLoc = S;
1685 return Op;
1686 }
1687
Oliver Stannarda34e4702015-12-01 10:48:51 +00001688 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1689 StringRef Str,
1690 SMLoc S,
1691 MCContext &Ctx) {
1692 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1693 Op->PSBHint.Val = Val;
1694 Op->PSBHint.Data = Str.data();
1695 Op->PSBHint.Length = Str.size();
1696 Op->StartLoc = S;
1697 Op->EndLoc = S;
1698 return Op;
1699 }
1700
David Blaikie960ea3f2014-06-08 16:18:35 +00001701 static std::unique_ptr<AArch64Operand>
1702 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1703 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1704 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001705 Op->ShiftExtend.Type = ShOp;
1706 Op->ShiftExtend.Amount = Val;
1707 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1708 Op->StartLoc = S;
1709 Op->EndLoc = E;
1710 return Op;
1711 }
1712};
1713
1714} // end anonymous namespace.
1715
1716void AArch64Operand::print(raw_ostream &OS) const {
1717 switch (Kind) {
1718 case k_FPImm:
1719 OS << "<fpimm " << getFPImm() << "("
1720 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1721 break;
1722 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001723 StringRef Name = getBarrierName();
1724 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001725 OS << "<barrier " << Name << ">";
1726 else
1727 OS << "<barrier invalid #" << getBarrier() << ">";
1728 break;
1729 }
1730 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001731 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001732 break;
1733 case k_ShiftedImm: {
1734 unsigned Shift = getShiftedImmShift();
1735 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001736 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001737 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1738 break;
1739 }
1740 case k_CondCode:
1741 OS << "<condcode " << getCondCode() << ">";
1742 break;
1743 case k_Register:
1744 OS << "<register " << getReg() << ">";
1745 break;
1746 case k_VectorList: {
1747 OS << "<vectorlist ";
1748 unsigned Reg = getVectorListStart();
1749 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1750 OS << Reg + i << " ";
1751 OS << ">";
1752 break;
1753 }
1754 case k_VectorIndex:
1755 OS << "<vectorindex " << getVectorIndex() << ">";
1756 break;
1757 case k_SysReg:
1758 OS << "<sysreg: " << getSysReg() << '>';
1759 break;
1760 case k_Token:
1761 OS << "'" << getToken() << "'";
1762 break;
1763 case k_SysCR:
1764 OS << "c" << getSysCR();
1765 break;
1766 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001767 StringRef Name = getPrefetchName();
1768 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001769 OS << "<prfop " << Name << ">";
1770 else
1771 OS << "<prfop invalid #" << getPrefetch() << ">";
1772 break;
1773 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001774 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001775 OS << getPSBHintName();
1776 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001777 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001778 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1779 << getShiftExtendAmount();
1780 if (!hasShiftExtendAmount())
1781 OS << "<imp>";
1782 OS << '>';
1783 break;
1784 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001785}
1786
1787/// @name Auto-generated Match Functions
1788/// {
1789
1790static unsigned MatchRegisterName(StringRef Name);
1791
1792/// }
1793
1794static unsigned matchVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001795 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001796 .Case("v0", AArch64::Q0)
1797 .Case("v1", AArch64::Q1)
1798 .Case("v2", AArch64::Q2)
1799 .Case("v3", AArch64::Q3)
1800 .Case("v4", AArch64::Q4)
1801 .Case("v5", AArch64::Q5)
1802 .Case("v6", AArch64::Q6)
1803 .Case("v7", AArch64::Q7)
1804 .Case("v8", AArch64::Q8)
1805 .Case("v9", AArch64::Q9)
1806 .Case("v10", AArch64::Q10)
1807 .Case("v11", AArch64::Q11)
1808 .Case("v12", AArch64::Q12)
1809 .Case("v13", AArch64::Q13)
1810 .Case("v14", AArch64::Q14)
1811 .Case("v15", AArch64::Q15)
1812 .Case("v16", AArch64::Q16)
1813 .Case("v17", AArch64::Q17)
1814 .Case("v18", AArch64::Q18)
1815 .Case("v19", AArch64::Q19)
1816 .Case("v20", AArch64::Q20)
1817 .Case("v21", AArch64::Q21)
1818 .Case("v22", AArch64::Q22)
1819 .Case("v23", AArch64::Q23)
1820 .Case("v24", AArch64::Q24)
1821 .Case("v25", AArch64::Q25)
1822 .Case("v26", AArch64::Q26)
1823 .Case("v27", AArch64::Q27)
1824 .Case("v28", AArch64::Q28)
1825 .Case("v29", AArch64::Q29)
1826 .Case("v30", AArch64::Q30)
1827 .Case("v31", AArch64::Q31)
1828 .Default(0);
1829}
1830
1831static bool isValidVectorKind(StringRef Name) {
1832 return StringSwitch<bool>(Name.lower())
1833 .Case(".8b", true)
1834 .Case(".16b", true)
1835 .Case(".4h", true)
1836 .Case(".8h", true)
1837 .Case(".2s", true)
1838 .Case(".4s", true)
1839 .Case(".1d", true)
1840 .Case(".2d", true)
1841 .Case(".1q", true)
1842 // Accept the width neutral ones, too, for verbose syntax. If those
1843 // aren't used in the right places, the token operand won't match so
1844 // all will work out.
1845 .Case(".b", true)
1846 .Case(".h", true)
1847 .Case(".s", true)
1848 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001849 // Needed for fp16 scalar pairwise reductions
1850 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001851 // another special case for the ARMv8.2a dot product operand
1852 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001853 .Default(false);
1854}
1855
1856static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1857 char &ElementKind) {
1858 assert(isValidVectorKind(Name));
1859
1860 ElementKind = Name.lower()[Name.size() - 1];
1861 NumElements = 0;
1862
1863 if (Name.size() == 2)
1864 return;
1865
1866 // Parse the lane count
1867 Name = Name.drop_front();
1868 while (isdigit(Name.front())) {
1869 NumElements = 10 * NumElements + (Name.front() - '0');
1870 Name = Name.drop_front();
1871 }
1872}
1873
1874bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1875 SMLoc &EndLoc) {
1876 StartLoc = getLoc();
1877 RegNo = tryParseRegister();
1878 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1879 return (RegNo == (unsigned)-1);
1880}
1881
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001882// Matches a register name or register alias previously defined by '.req'
1883unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
1884 bool isVector) {
1885 unsigned RegNum = isVector ? matchVectorRegName(Name)
1886 : MatchRegisterName(Name);
1887
1888 if (RegNum == 0) {
1889 // Check for aliases registered via .req. Canonicalize to lower case.
1890 // That's more consistent since register names are case insensitive, and
1891 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1892 auto Entry = RegisterReqs.find(Name.lower());
1893 if (Entry == RegisterReqs.end())
1894 return 0;
1895 // set RegNum if the match is the right kind of register
1896 if (isVector == Entry->getValue().first)
1897 RegNum = Entry->getValue().second;
1898 }
1899 return RegNum;
1900}
1901
Tim Northover3b0846e2014-05-24 12:50:23 +00001902/// tryParseRegister - Try to parse a register name. The token must be an
1903/// Identifier when called, and if it is a register name the token is eaten and
1904/// the register is added to the operand list.
1905int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001906 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001907 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001908 if (Tok.isNot(AsmToken::Identifier))
1909 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00001910
1911 std::string lowerCase = Tok.getString().lower();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001912 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
Tim Northover3b0846e2014-05-24 12:50:23 +00001913 // Also handle a few aliases of registers.
1914 if (RegNum == 0)
1915 RegNum = StringSwitch<unsigned>(lowerCase)
1916 .Case("fp", AArch64::FP)
1917 .Case("lr", AArch64::LR)
1918 .Case("x31", AArch64::XZR)
1919 .Case("w31", AArch64::WZR)
1920 .Default(0);
1921
1922 if (RegNum == 0)
1923 return -1;
1924
1925 Parser.Lex(); // Eat identifier token.
1926 return RegNum;
1927}
1928
1929/// tryMatchVectorRegister - Try to parse a vector register name with optional
1930/// kind specifier. If it is a register specifier, eat the token and return it.
1931int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001932 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001933 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1934 TokError("vector register expected");
1935 return -1;
1936 }
1937
1938 StringRef Name = Parser.getTok().getString();
1939 // If there is a kind specifier, it's separated from the register name by
1940 // a '.'.
1941 size_t Start = 0, Next = Name.find('.');
1942 StringRef Head = Name.slice(Start, Next);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001943 unsigned RegNum = matchRegisterNameAlias(Head, true);
1944
Tim Northover3b0846e2014-05-24 12:50:23 +00001945 if (RegNum) {
1946 if (Next != StringRef::npos) {
1947 Kind = Name.slice(Next, StringRef::npos);
1948 if (!isValidVectorKind(Kind)) {
1949 TokError("invalid vector kind qualifier");
1950 return -1;
1951 }
1952 }
1953 Parser.Lex(); // Eat the register token.
1954 return RegNum;
1955 }
1956
1957 if (expected)
1958 TokError("vector register expected");
1959 return -1;
1960}
1961
1962/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00001963OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001964AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001965 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001966 SMLoc S = getLoc();
1967
1968 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1969 Error(S, "Expected cN operand where 0 <= N <= 15");
1970 return MatchOperand_ParseFail;
1971 }
1972
1973 StringRef Tok = Parser.getTok().getIdentifier();
1974 if (Tok[0] != 'c' && Tok[0] != 'C') {
1975 Error(S, "Expected cN operand where 0 <= N <= 15");
1976 return MatchOperand_ParseFail;
1977 }
1978
1979 uint32_t CRNum;
1980 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
1981 if (BadNum || CRNum > 15) {
1982 Error(S, "Expected cN operand where 0 <= N <= 15");
1983 return MatchOperand_ParseFail;
1984 }
1985
1986 Parser.Lex(); // Eat identifier token.
1987 Operands.push_back(
1988 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
1989 return MatchOperand_Success;
1990}
1991
1992/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00001993OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001994AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001995 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001996 SMLoc S = getLoc();
1997 const AsmToken &Tok = Parser.getTok();
1998 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00001999 // Eat optional hash.
2000 if (parseOptionalToken(AsmToken::Hash) ||
2001 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002002 const MCExpr *ImmVal;
2003 if (getParser().parseExpression(ImmVal))
2004 return MatchOperand_ParseFail;
2005
2006 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2007 if (!MCE) {
2008 TokError("immediate value expected for prefetch operand");
2009 return MatchOperand_ParseFail;
2010 }
2011 unsigned prfop = MCE->getValue();
2012 if (prfop > 31) {
2013 TokError("prefetch operand out of range, [0,31] expected");
2014 return MatchOperand_ParseFail;
2015 }
2016
Tim Northovere6ae6762016-07-05 21:23:04 +00002017 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2018 Operands.push_back(AArch64Operand::CreatePrefetch(
2019 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002020 return MatchOperand_Success;
2021 }
2022
2023 if (Tok.isNot(AsmToken::Identifier)) {
2024 TokError("pre-fetch hint expected");
2025 return MatchOperand_ParseFail;
2026 }
2027
Tim Northovere6ae6762016-07-05 21:23:04 +00002028 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2029 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002030 TokError("pre-fetch hint expected");
2031 return MatchOperand_ParseFail;
2032 }
2033
2034 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002035 Operands.push_back(AArch64Operand::CreatePrefetch(
2036 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002037 return MatchOperand_Success;
2038}
2039
Oliver Stannarda34e4702015-12-01 10:48:51 +00002040/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002041OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002042AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2043 MCAsmParser &Parser = getParser();
2044 SMLoc S = getLoc();
2045 const AsmToken &Tok = Parser.getTok();
2046 if (Tok.isNot(AsmToken::Identifier)) {
2047 TokError("invalid operand for instruction");
2048 return MatchOperand_ParseFail;
2049 }
2050
Tim Northovere6ae6762016-07-05 21:23:04 +00002051 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2052 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002053 TokError("invalid operand for instruction");
2054 return MatchOperand_ParseFail;
2055 }
2056
2057 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002058 Operands.push_back(AArch64Operand::CreatePSBHint(
2059 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002060 return MatchOperand_Success;
2061}
2062
Tim Northover3b0846e2014-05-24 12:50:23 +00002063/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2064/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002065OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002066AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002067 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002068 SMLoc S = getLoc();
2069 const MCExpr *Expr;
2070
2071 if (Parser.getTok().is(AsmToken::Hash)) {
2072 Parser.Lex(); // Eat hash token.
2073 }
2074
2075 if (parseSymbolicImmVal(Expr))
2076 return MatchOperand_ParseFail;
2077
2078 AArch64MCExpr::VariantKind ELFRefKind;
2079 MCSymbolRefExpr::VariantKind DarwinRefKind;
2080 int64_t Addend;
2081 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2082 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2083 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2084 // No modifier was specified at all; this is the syntax for an ELF basic
2085 // ADRP relocation (unfortunately).
2086 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002087 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002088 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2089 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2090 Addend != 0) {
2091 Error(S, "gotpage label reference not allowed an addend");
2092 return MatchOperand_ParseFail;
2093 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2094 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2095 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2096 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2097 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2098 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2099 // The operand must be an @page or @gotpage qualified symbolref.
2100 Error(S, "page or gotpage label reference expected");
2101 return MatchOperand_ParseFail;
2102 }
2103 }
2104
2105 // We have either a label reference possibly with addend or an immediate. The
2106 // addend is a raw value here. The linker will adjust it to only reference the
2107 // page.
2108 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2109 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2110
2111 return MatchOperand_Success;
2112}
2113
2114/// tryParseAdrLabel - Parse and validate a source label for the ADR
2115/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002116OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002117AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2118 SMLoc S = getLoc();
2119 const MCExpr *Expr;
2120
Nirav Davee833c6c2016-11-08 18:31:04 +00002121 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002122 if (getParser().parseExpression(Expr))
2123 return MatchOperand_ParseFail;
2124
2125 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2126 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2127
2128 return MatchOperand_Success;
2129}
2130
2131/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002132OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002133AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002134 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002135 SMLoc S = getLoc();
2136
Nirav Davee833c6c2016-11-08 18:31:04 +00002137 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002138
2139 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002140 bool isNegative = parseOptionalToken(AsmToken::Minus);
2141
Tim Northover3b0846e2014-05-24 12:50:23 +00002142 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002143 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002144 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002145 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002146 Val = Tok.getIntVal();
2147 if (Val > 255 || Val < 0) {
2148 TokError("encoded floating point value out of range");
2149 return MatchOperand_ParseFail;
2150 }
2151 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002152 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002153 if (isNegative)
2154 RealVal.changeSign();
2155
Tim Northover3b0846e2014-05-24 12:50:23 +00002156 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002157 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002158
John Brawn5ca5daa2017-04-20 10:13:54 +00002159 // Check for out of range values. As an exception we let Zero through,
2160 // but as tokens instead of an FPImm so that it can be matched by the
2161 // appropriate alias if one exists.
2162 if (RealVal.isPosZero()) {
2163 Parser.Lex(); // Eat the token.
2164 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2165 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2166 return MatchOperand_Success;
2167 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002168 TokError("expected compatible register or floating-point constant");
2169 return MatchOperand_ParseFail;
2170 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002171 }
2172 Parser.Lex(); // Eat the token.
2173 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2174 return MatchOperand_Success;
2175 }
2176
2177 if (!Hash)
2178 return MatchOperand_NoMatch;
2179
2180 TokError("invalid floating point immediate");
2181 return MatchOperand_ParseFail;
2182}
2183
2184/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002185OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002186AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002187 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002188 SMLoc S = getLoc();
2189
2190 if (Parser.getTok().is(AsmToken::Hash))
2191 Parser.Lex(); // Eat '#'
2192 else if (Parser.getTok().isNot(AsmToken::Integer))
2193 // Operand should start from # or should be integer, emit error otherwise.
2194 return MatchOperand_NoMatch;
2195
2196 const MCExpr *Imm;
2197 if (parseSymbolicImmVal(Imm))
2198 return MatchOperand_ParseFail;
2199 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2200 uint64_t ShiftAmount = 0;
2201 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2202 if (MCE) {
2203 int64_t Val = MCE->getValue();
2204 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002205 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002206 ShiftAmount = 12;
2207 }
2208 }
2209 SMLoc E = Parser.getTok().getLoc();
2210 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2211 getContext()));
2212 return MatchOperand_Success;
2213 }
2214
2215 // Eat ','
2216 Parser.Lex();
2217
2218 // The optional operand must be "lsl #N" where N is non-negative.
2219 if (!Parser.getTok().is(AsmToken::Identifier) ||
2220 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2221 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2222 return MatchOperand_ParseFail;
2223 }
2224
2225 // Eat 'lsl'
2226 Parser.Lex();
2227
Nirav Davee833c6c2016-11-08 18:31:04 +00002228 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002229
2230 if (Parser.getTok().isNot(AsmToken::Integer)) {
2231 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2232 return MatchOperand_ParseFail;
2233 }
2234
2235 int64_t ShiftAmount = Parser.getTok().getIntVal();
2236
2237 if (ShiftAmount < 0) {
2238 Error(Parser.getTok().getLoc(), "positive shift amount required");
2239 return MatchOperand_ParseFail;
2240 }
2241 Parser.Lex(); // Eat the number
2242
2243 SMLoc E = Parser.getTok().getLoc();
2244 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2245 S, E, getContext()));
2246 return MatchOperand_Success;
2247}
2248
2249/// parseCondCodeString - Parse a Condition Code string.
2250AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2251 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2252 .Case("eq", AArch64CC::EQ)
2253 .Case("ne", AArch64CC::NE)
2254 .Case("cs", AArch64CC::HS)
2255 .Case("hs", AArch64CC::HS)
2256 .Case("cc", AArch64CC::LO)
2257 .Case("lo", AArch64CC::LO)
2258 .Case("mi", AArch64CC::MI)
2259 .Case("pl", AArch64CC::PL)
2260 .Case("vs", AArch64CC::VS)
2261 .Case("vc", AArch64CC::VC)
2262 .Case("hi", AArch64CC::HI)
2263 .Case("ls", AArch64CC::LS)
2264 .Case("ge", AArch64CC::GE)
2265 .Case("lt", AArch64CC::LT)
2266 .Case("gt", AArch64CC::GT)
2267 .Case("le", AArch64CC::LE)
2268 .Case("al", AArch64CC::AL)
2269 .Case("nv", AArch64CC::NV)
2270 .Default(AArch64CC::Invalid);
2271 return CC;
2272}
2273
2274/// parseCondCode - Parse a Condition Code operand.
2275bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2276 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002277 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002278 SMLoc S = getLoc();
2279 const AsmToken &Tok = Parser.getTok();
2280 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2281
2282 StringRef Cond = Tok.getString();
2283 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2284 if (CC == AArch64CC::Invalid)
2285 return TokError("invalid condition code");
2286 Parser.Lex(); // Eat identifier token.
2287
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002288 if (invertCondCode) {
2289 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2290 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002291 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002292 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002293
2294 Operands.push_back(
2295 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2296 return false;
2297}
2298
2299/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2300/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002301OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002302AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002303 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002304 const AsmToken &Tok = Parser.getTok();
2305 std::string LowerID = Tok.getString().lower();
2306 AArch64_AM::ShiftExtendType ShOp =
2307 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2308 .Case("lsl", AArch64_AM::LSL)
2309 .Case("lsr", AArch64_AM::LSR)
2310 .Case("asr", AArch64_AM::ASR)
2311 .Case("ror", AArch64_AM::ROR)
2312 .Case("msl", AArch64_AM::MSL)
2313 .Case("uxtb", AArch64_AM::UXTB)
2314 .Case("uxth", AArch64_AM::UXTH)
2315 .Case("uxtw", AArch64_AM::UXTW)
2316 .Case("uxtx", AArch64_AM::UXTX)
2317 .Case("sxtb", AArch64_AM::SXTB)
2318 .Case("sxth", AArch64_AM::SXTH)
2319 .Case("sxtw", AArch64_AM::SXTW)
2320 .Case("sxtx", AArch64_AM::SXTX)
2321 .Default(AArch64_AM::InvalidShiftExtend);
2322
2323 if (ShOp == AArch64_AM::InvalidShiftExtend)
2324 return MatchOperand_NoMatch;
2325
2326 SMLoc S = Tok.getLoc();
2327 Parser.Lex();
2328
Nirav Davee833c6c2016-11-08 18:31:04 +00002329 bool Hash = parseOptionalToken(AsmToken::Hash);
2330
Tim Northover3b0846e2014-05-24 12:50:23 +00002331 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2332 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2333 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2334 ShOp == AArch64_AM::MSL) {
2335 // We expect a number here.
2336 TokError("expected #imm after shift specifier");
2337 return MatchOperand_ParseFail;
2338 }
2339
Chad Rosier2ff37b82016-12-27 16:58:09 +00002340 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002341 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2342 Operands.push_back(
2343 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2344 return MatchOperand_Success;
2345 }
2346
Chad Rosier2ff37b82016-12-27 16:58:09 +00002347 // Make sure we do actually have a number, identifier or a parenthesized
2348 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002349 SMLoc E = Parser.getTok().getLoc();
2350 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002351 !Parser.getTok().is(AsmToken::LParen) &&
2352 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002353 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002354 return MatchOperand_ParseFail;
2355 }
2356
2357 const MCExpr *ImmVal;
2358 if (getParser().parseExpression(ImmVal))
2359 return MatchOperand_ParseFail;
2360
2361 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2362 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002363 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002364 return MatchOperand_ParseFail;
2365 }
2366
Jim Grosbach57fd2622014-09-23 22:16:02 +00002367 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002368 Operands.push_back(AArch64Operand::CreateShiftExtend(
2369 ShOp, MCE->getValue(), true, S, E, getContext()));
2370 return MatchOperand_Success;
2371}
2372
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002373static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2374 if (FBS[AArch64::HasV8_1aOps])
2375 Str += "ARMv8.1a";
2376 else if (FBS[AArch64::HasV8_2aOps])
2377 Str += "ARMv8.2a";
2378 else
2379 Str += "(unknown)";
2380}
2381
2382void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2383 SMLoc S) {
2384 const uint16_t Op2 = Encoding & 7;
2385 const uint16_t Cm = (Encoding & 0x78) >> 3;
2386 const uint16_t Cn = (Encoding & 0x780) >> 7;
2387 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2388
2389 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2390
2391 Operands.push_back(
2392 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2393 Operands.push_back(
2394 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2395 Operands.push_back(
2396 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2397 Expr = MCConstantExpr::create(Op2, getContext());
2398 Operands.push_back(
2399 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2400}
2401
Tim Northover3b0846e2014-05-24 12:50:23 +00002402/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2403/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2404bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2405 OperandVector &Operands) {
2406 if (Name.find('.') != StringRef::npos)
2407 return TokError("invalid operand");
2408
2409 Mnemonic = Name;
2410 Operands.push_back(
2411 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2412
Rafael Espindola961d4692014-11-11 05:18:41 +00002413 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002414 const AsmToken &Tok = Parser.getTok();
2415 StringRef Op = Tok.getString();
2416 SMLoc S = Tok.getLoc();
2417
Tim Northover3b0846e2014-05-24 12:50:23 +00002418 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002419 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2420 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002421 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002422 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2423 std::string Str("IC " + std::string(IC->Name) + " requires ");
2424 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2425 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002426 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002427 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002428 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002429 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2430 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002431 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002432 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2433 std::string Str("DC " + std::string(DC->Name) + " requires ");
2434 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2435 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002436 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002437 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002438 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002439 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2440 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002441 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002442 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2443 std::string Str("AT " + std::string(AT->Name) + " requires ");
2444 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2445 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002446 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002447 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002448 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002449 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2450 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002451 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002452 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2453 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2454 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2455 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002456 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002457 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002458 }
2459
Tim Northover3b0846e2014-05-24 12:50:23 +00002460 Parser.Lex(); // Eat operand.
2461
2462 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2463 bool HasRegister = false;
2464
2465 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002466 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002467 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2468 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002469 HasRegister = true;
2470 }
2471
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002472 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002473 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002474 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002475 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002476
Nirav Davee833c6c2016-11-08 18:31:04 +00002477 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2478 return true;
2479
Tim Northover3b0846e2014-05-24 12:50:23 +00002480 return false;
2481}
2482
Alex Bradbury58eba092016-11-01 16:32:05 +00002483OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002484AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002485 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002486 const AsmToken &Tok = Parser.getTok();
2487
2488 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002489 if (parseOptionalToken(AsmToken::Hash) ||
2490 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002491 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002492 const MCExpr *ImmVal;
2493 SMLoc ExprLoc = getLoc();
2494 if (getParser().parseExpression(ImmVal))
2495 return MatchOperand_ParseFail;
2496 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2497 if (!MCE) {
2498 Error(ExprLoc, "immediate value expected for barrier operand");
2499 return MatchOperand_ParseFail;
2500 }
2501 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2502 Error(ExprLoc, "barrier operand out of range");
2503 return MatchOperand_ParseFail;
2504 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002505 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2506 Operands.push_back(AArch64Operand::CreateBarrier(
2507 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002508 return MatchOperand_Success;
2509 }
2510
2511 if (Tok.isNot(AsmToken::Identifier)) {
2512 TokError("invalid operand for instruction");
2513 return MatchOperand_ParseFail;
2514 }
2515
Tim Northover3b0846e2014-05-24 12:50:23 +00002516 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002517 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2518 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 TokError("'sy' or #imm operand expected");
2520 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002521 } else if (!DB) {
2522 TokError("invalid barrier option name");
2523 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002524 }
2525
Tim Northovere6ae6762016-07-05 21:23:04 +00002526 Operands.push_back(AArch64Operand::CreateBarrier(
2527 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002528 Parser.Lex(); // Consume the option
2529
2530 return MatchOperand_Success;
2531}
2532
Alex Bradbury58eba092016-11-01 16:32:05 +00002533OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002534AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002535 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002536 const AsmToken &Tok = Parser.getTok();
2537
2538 if (Tok.isNot(AsmToken::Identifier))
2539 return MatchOperand_NoMatch;
2540
Tim Northovere6ae6762016-07-05 21:23:04 +00002541 int MRSReg, MSRReg;
2542 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2543 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2544 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2545 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2546 } else
2547 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002548
Tim Northovere6ae6762016-07-05 21:23:04 +00002549 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2550 unsigned PStateImm = -1;
2551 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2552 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002553
Tim Northovere6ae6762016-07-05 21:23:04 +00002554 Operands.push_back(
2555 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2556 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 Parser.Lex(); // Eat identifier
2558
2559 return MatchOperand_Success;
2560}
2561
2562/// tryParseVectorRegister - Parse a vector register operand.
2563bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002564 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002565 if (Parser.getTok().isNot(AsmToken::Identifier))
2566 return true;
2567
2568 SMLoc S = getLoc();
2569 // Check for a vector register specifier first.
2570 StringRef Kind;
2571 int64_t Reg = tryMatchVectorRegister(Kind, false);
2572 if (Reg == -1)
2573 return true;
2574 Operands.push_back(
2575 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2576 // If there was an explicit qualifier, that goes on as a literal text
2577 // operand.
2578 if (!Kind.empty())
2579 Operands.push_back(
2580 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2581
2582 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002583 SMLoc SIdx = getLoc();
2584 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002585 const MCExpr *ImmVal;
2586 if (getParser().parseExpression(ImmVal))
2587 return false;
2588 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2589 if (!MCE) {
2590 TokError("immediate value expected for vector index");
2591 return false;
2592 }
2593
2594 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002595
Nirav Davee833c6c2016-11-08 18:31:04 +00002596 if (parseToken(AsmToken::RBrac, "']' expected"))
2597 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002598
2599 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2600 E, getContext()));
2601 }
2602
2603 return false;
2604}
2605
2606/// parseRegister - Parse a non-vector register operand.
2607bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2608 SMLoc S = getLoc();
2609 // Try for a vector register.
2610 if (!tryParseVectorRegister(Operands))
2611 return false;
2612
2613 // Try for a scalar register.
2614 int64_t Reg = tryParseRegister();
2615 if (Reg == -1)
2616 return true;
2617 Operands.push_back(
2618 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2619
Tim Northover3b0846e2014-05-24 12:50:23 +00002620 return false;
2621}
2622
2623bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002624 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002625 bool HasELFModifier = false;
2626 AArch64MCExpr::VariantKind RefKind;
2627
Nirav Davee833c6c2016-11-08 18:31:04 +00002628 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 HasELFModifier = true;
2630
Nirav Davee833c6c2016-11-08 18:31:04 +00002631 if (Parser.getTok().isNot(AsmToken::Identifier))
2632 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002633
2634 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2635 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2636 .Case("lo12", AArch64MCExpr::VK_LO12)
2637 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2638 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2639 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2640 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2641 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2642 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2643 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2644 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2645 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2646 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2647 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2648 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2649 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2650 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2651 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2652 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2653 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2654 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2655 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2656 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2657 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2658 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2659 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2660 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2661 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2662 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2663 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2664 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2665 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2666 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2667 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2668 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2669 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2670 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2671 .Default(AArch64MCExpr::VK_INVALID);
2672
Nirav Davee833c6c2016-11-08 18:31:04 +00002673 if (RefKind == AArch64MCExpr::VK_INVALID)
2674 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002675
2676 Parser.Lex(); // Eat identifier
2677
Nirav Davee833c6c2016-11-08 18:31:04 +00002678 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002679 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002680 }
2681
2682 if (getParser().parseExpression(ImmVal))
2683 return true;
2684
2685 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002686 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002687
2688 return false;
2689}
2690
2691/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2692bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002693 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002694 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2695 SMLoc S = getLoc();
2696 Parser.Lex(); // Eat left bracket token.
2697 StringRef Kind;
2698 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2699 if (FirstReg == -1)
2700 return true;
2701 int64_t PrevReg = FirstReg;
2702 unsigned Count = 1;
2703
Nirav Davee833c6c2016-11-08 18:31:04 +00002704 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002705 SMLoc Loc = getLoc();
2706 StringRef NextKind;
2707 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2708 if (Reg == -1)
2709 return true;
2710 // Any Kind suffices must match on all regs in the list.
2711 if (Kind != NextKind)
2712 return Error(Loc, "mismatched register size suffix");
2713
2714 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2715
2716 if (Space == 0 || Space > 3) {
2717 return Error(Loc, "invalid number of vectors");
2718 }
2719
2720 Count += Space;
2721 }
2722 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002723 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002724 SMLoc Loc = getLoc();
2725 StringRef NextKind;
2726 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2727 if (Reg == -1)
2728 return true;
2729 // Any Kind suffices must match on all regs in the list.
2730 if (Kind != NextKind)
2731 return Error(Loc, "mismatched register size suffix");
2732
2733 // Registers must be incremental (with wraparound at 31)
2734 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2735 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2736 return Error(Loc, "registers must be sequential");
2737
2738 PrevReg = Reg;
2739 ++Count;
2740 }
2741 }
2742
Nirav Davee833c6c2016-11-08 18:31:04 +00002743 if (parseToken(AsmToken::RCurly, "'}' expected"))
2744 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002745
2746 if (Count > 4)
2747 return Error(S, "invalid number of vectors");
2748
2749 unsigned NumElements = 0;
2750 char ElementKind = 0;
2751 if (!Kind.empty())
2752 parseValidVectorKind(Kind, NumElements, ElementKind);
2753
2754 Operands.push_back(AArch64Operand::CreateVectorList(
2755 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2756
2757 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002758 SMLoc SIdx = getLoc();
2759 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002760 const MCExpr *ImmVal;
2761 if (getParser().parseExpression(ImmVal))
2762 return false;
2763 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2764 if (!MCE) {
2765 TokError("immediate value expected for vector index");
2766 return false;
2767 }
2768
2769 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002770 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002771 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002772
2773 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2774 E, getContext()));
2775 }
2776 return false;
2777}
2778
Alex Bradbury58eba092016-11-01 16:32:05 +00002779OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002780AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002781 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002782 const AsmToken &Tok = Parser.getTok();
2783 if (!Tok.is(AsmToken::Identifier))
2784 return MatchOperand_NoMatch;
2785
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002786 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00002787
2788 MCContext &Ctx = getContext();
2789 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2790 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2791 return MatchOperand_NoMatch;
2792
2793 SMLoc S = getLoc();
2794 Parser.Lex(); // Eat register
2795
Nirav Davee833c6c2016-11-08 18:31:04 +00002796 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002797 Operands.push_back(
2798 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2799 return MatchOperand_Success;
2800 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002801
Nirav Davee833c6c2016-11-08 18:31:04 +00002802 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002803
2804 if (Parser.getTok().isNot(AsmToken::Integer)) {
2805 Error(getLoc(), "index must be absent or #0");
2806 return MatchOperand_ParseFail;
2807 }
2808
2809 const MCExpr *ImmVal;
2810 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2811 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2812 Error(getLoc(), "index must be absent or #0");
2813 return MatchOperand_ParseFail;
2814 }
2815
2816 Operands.push_back(
2817 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2818 return MatchOperand_Success;
2819}
2820
2821/// parseOperand - Parse a arm instruction operand. For now this parses the
2822/// operand regardless of the mnemonic.
2823bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
2824 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002825 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002826 // Check if the current operand has a custom associated parser, if so, try to
2827 // custom parse the operand, or fallback to the general approach.
2828 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2829 if (ResTy == MatchOperand_Success)
2830 return false;
2831 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2832 // there was a match, but an error occurred, in which case, just return that
2833 // the operand parsing failed.
2834 if (ResTy == MatchOperand_ParseFail)
2835 return true;
2836
2837 // Nothing custom, so do general case parsing.
2838 SMLoc S, E;
2839 switch (getLexer().getKind()) {
2840 default: {
2841 SMLoc S = getLoc();
2842 const MCExpr *Expr;
2843 if (parseSymbolicImmVal(Expr))
2844 return Error(S, "invalid operand");
2845
2846 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2847 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2848 return false;
2849 }
2850 case AsmToken::LBrac: {
2851 SMLoc Loc = Parser.getTok().getLoc();
2852 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
2853 getContext()));
2854 Parser.Lex(); // Eat '['
2855
2856 // There's no comma after a '[', so we can parse the next operand
2857 // immediately.
2858 return parseOperand(Operands, false, false);
2859 }
2860 case AsmToken::LCurly:
2861 return parseVectorList(Operands);
2862 case AsmToken::Identifier: {
2863 // If we're expecting a Condition Code operand, then just parse that.
2864 if (isCondCode)
2865 return parseCondCode(Operands, invertCondCode);
2866
2867 // If it's a register name, parse it.
2868 if (!parseRegister(Operands))
2869 return false;
2870
2871 // This could be an optional "shift" or "extend" operand.
2872 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
2873 // We can only continue if no tokens were eaten.
2874 if (GotShift != MatchOperand_NoMatch)
2875 return GotShift;
2876
2877 // This was not a register so parse other operands that start with an
2878 // identifier (like labels) as expressions and create them as immediates.
2879 const MCExpr *IdVal;
2880 S = getLoc();
2881 if (getParser().parseExpression(IdVal))
2882 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002883 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2884 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
2885 return false;
2886 }
2887 case AsmToken::Integer:
2888 case AsmToken::Real:
2889 case AsmToken::Hash: {
2890 // #42 -> immediate.
2891 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002892
2893 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002894
2895 // Parse a negative sign
2896 bool isNegative = false;
2897 if (Parser.getTok().is(AsmToken::Minus)) {
2898 isNegative = true;
2899 // We need to consume this token only when we have a Real, otherwise
2900 // we let parseSymbolicImmVal take care of it
2901 if (Parser.getLexer().peekTok().is(AsmToken::Real))
2902 Parser.Lex();
2903 }
2904
2905 // The only Real that should come through here is a literal #0.0 for
2906 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
2907 // so convert the value.
2908 const AsmToken &Tok = Parser.getTok();
2909 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002910 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002911 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2912 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
2913 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
2914 Mnemonic != "fcmlt")
2915 return TokError("unexpected floating point literal");
2916 else if (IntVal != 0 || isNegative)
2917 return TokError("expected floating-point constant #0.0");
2918 Parser.Lex(); // Eat the token.
2919
2920 Operands.push_back(
2921 AArch64Operand::CreateToken("#0", false, S, getContext()));
2922 Operands.push_back(
2923 AArch64Operand::CreateToken(".0", false, S, getContext()));
2924 return false;
2925 }
2926
2927 const MCExpr *ImmVal;
2928 if (parseSymbolicImmVal(ImmVal))
2929 return true;
2930
2931 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2932 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
2933 return false;
2934 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002935 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00002936 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002937 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00002938 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002939 Parser.Lex(); // Eat '='
2940 const MCExpr *SubExprVal;
2941 if (getParser().parseExpression(SubExprVal))
2942 return true;
2943
David Peixottoae5ba762014-07-18 16:05:14 +00002944 if (Operands.size() < 2 ||
2945 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00002946 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00002947
2948 bool IsXReg =
2949 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
2950 Operands[1]->getReg());
2951
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002952 MCContext& Ctx = getContext();
2953 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
2954 // 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 +00002955 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002956 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
2957 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
2958 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
2959 ShiftAmt += 16;
2960 Imm >>= 16;
2961 }
2962 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
2963 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
2964 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00002965 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002966 if (ShiftAmt)
2967 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
2968 ShiftAmt, true, S, E, Ctx));
2969 return false;
2970 }
David Peixottoae5ba762014-07-18 16:05:14 +00002971 APInt Simm = APInt(64, Imm << ShiftAmt);
2972 // check if the immediate is an unsigned or signed 32-bit int for W regs
2973 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
2974 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002975 }
2976 // 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 +00002977 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00002978 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002979 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
2980 return false;
2981 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002982 }
2983}
2984
2985/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
2986/// operands.
2987bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
2988 StringRef Name, SMLoc NameLoc,
2989 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002990 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002991 Name = StringSwitch<StringRef>(Name.lower())
2992 .Case("beq", "b.eq")
2993 .Case("bne", "b.ne")
2994 .Case("bhs", "b.hs")
2995 .Case("bcs", "b.cs")
2996 .Case("blo", "b.lo")
2997 .Case("bcc", "b.cc")
2998 .Case("bmi", "b.mi")
2999 .Case("bpl", "b.pl")
3000 .Case("bvs", "b.vs")
3001 .Case("bvc", "b.vc")
3002 .Case("bhi", "b.hi")
3003 .Case("bls", "b.ls")
3004 .Case("bge", "b.ge")
3005 .Case("blt", "b.lt")
3006 .Case("bgt", "b.gt")
3007 .Case("ble", "b.le")
3008 .Case("bal", "b.al")
3009 .Case("bnv", "b.nv")
3010 .Default(Name);
3011
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003012 // First check for the AArch64-specific .req directive.
3013 if (Parser.getTok().is(AsmToken::Identifier) &&
3014 Parser.getTok().getIdentifier() == ".req") {
3015 parseDirectiveReq(Name, NameLoc);
3016 // We always return 'error' for this, as we're done with this
3017 // statement and don't need to match the 'instruction."
3018 return true;
3019 }
3020
Tim Northover3b0846e2014-05-24 12:50:23 +00003021 // Create the leading tokens for the mnemonic, split by '.' characters.
3022 size_t Start = 0, Next = Name.find('.');
3023 StringRef Head = Name.slice(Start, Next);
3024
3025 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003026 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3027 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003028
3029 Operands.push_back(
3030 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3031 Mnemonic = Head;
3032
3033 // Handle condition codes for a branch mnemonic
3034 if (Head == "b" && Next != StringRef::npos) {
3035 Start = Next;
3036 Next = Name.find('.', Start + 1);
3037 Head = Name.slice(Start + 1, Next);
3038
3039 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3040 (Head.data() - Name.data()));
3041 AArch64CC::CondCode CC = parseCondCodeString(Head);
3042 if (CC == AArch64CC::Invalid)
3043 return Error(SuffixLoc, "invalid condition code");
3044 Operands.push_back(
3045 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3046 Operands.push_back(
3047 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3048 }
3049
3050 // Add the remaining tokens in the mnemonic.
3051 while (Next != StringRef::npos) {
3052 Start = Next;
3053 Next = Name.find('.', Start + 1);
3054 Head = Name.slice(Start, Next);
3055 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3056 (Head.data() - Name.data()) + 1);
3057 Operands.push_back(
3058 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3059 }
3060
3061 // Conditional compare instructions have a Condition Code operand, which needs
3062 // to be parsed and an immediate operand created.
3063 bool condCodeFourthOperand =
3064 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3065 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3066 Head == "csinc" || Head == "csinv" || Head == "csneg");
3067
3068 // These instructions are aliases to some of the conditional select
3069 // instructions. However, the condition code is inverted in the aliased
3070 // instruction.
3071 //
3072 // FIXME: Is this the correct way to handle these? Or should the parser
3073 // generate the aliased instructions directly?
3074 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3075 bool condCodeThirdOperand =
3076 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3077
3078 // Read the remaining operands.
3079 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3080 // Read the first operand.
3081 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003082 return true;
3083 }
3084
3085 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003086 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003087 // Parse and remember the operand.
3088 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3089 (N == 3 && condCodeThirdOperand) ||
3090 (N == 2 && condCodeSecondOperand),
3091 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003092 return true;
3093 }
3094
3095 // After successfully parsing some operands there are two special cases to
3096 // consider (i.e. notional operands not separated by commas). Both are due
3097 // to memory specifiers:
3098 // + An RBrac will end an address for load/store/prefetch
3099 // + An '!' will indicate a pre-indexed operation.
3100 //
3101 // It's someone else's responsibility to make sure these tokens are sane
3102 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003103
Nirav Davee833c6c2016-11-08 18:31:04 +00003104 SMLoc RLoc = Parser.getTok().getLoc();
3105 if (parseOptionalToken(AsmToken::RBrac))
3106 Operands.push_back(
3107 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3108 SMLoc ELoc = Parser.getTok().getLoc();
3109 if (parseOptionalToken(AsmToken::Exclaim))
3110 Operands.push_back(
3111 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003112
3113 ++N;
3114 }
3115 }
3116
Nirav Davee833c6c2016-11-08 18:31:04 +00003117 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3118 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003119
Tim Northover3b0846e2014-05-24 12:50:23 +00003120 return false;
3121}
3122
3123// FIXME: This entire function is a giant hack to provide us with decent
3124// operand range validation/diagnostics until TableGen/MC can be extended
3125// to support autogeneration of this kind of validation.
3126bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3127 SmallVectorImpl<SMLoc> &Loc) {
3128 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3129 // Check for indexed addressing modes w/ the base register being the
3130 // same as a destination/source register or pair load where
3131 // the Rt == Rt2. All of those are undefined behaviour.
3132 switch (Inst.getOpcode()) {
3133 case AArch64::LDPSWpre:
3134 case AArch64::LDPWpost:
3135 case AArch64::LDPWpre:
3136 case AArch64::LDPXpost:
3137 case AArch64::LDPXpre: {
3138 unsigned Rt = Inst.getOperand(1).getReg();
3139 unsigned Rt2 = Inst.getOperand(2).getReg();
3140 unsigned Rn = Inst.getOperand(3).getReg();
3141 if (RI->isSubRegisterEq(Rn, Rt))
3142 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3143 "is also a destination");
3144 if (RI->isSubRegisterEq(Rn, Rt2))
3145 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3146 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003147 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003148 }
3149 case AArch64::LDPDi:
3150 case AArch64::LDPQi:
3151 case AArch64::LDPSi:
3152 case AArch64::LDPSWi:
3153 case AArch64::LDPWi:
3154 case AArch64::LDPXi: {
3155 unsigned Rt = Inst.getOperand(0).getReg();
3156 unsigned Rt2 = Inst.getOperand(1).getReg();
3157 if (Rt == Rt2)
3158 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3159 break;
3160 }
3161 case AArch64::LDPDpost:
3162 case AArch64::LDPDpre:
3163 case AArch64::LDPQpost:
3164 case AArch64::LDPQpre:
3165 case AArch64::LDPSpost:
3166 case AArch64::LDPSpre:
3167 case AArch64::LDPSWpost: {
3168 unsigned Rt = Inst.getOperand(1).getReg();
3169 unsigned Rt2 = Inst.getOperand(2).getReg();
3170 if (Rt == Rt2)
3171 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3172 break;
3173 }
3174 case AArch64::STPDpost:
3175 case AArch64::STPDpre:
3176 case AArch64::STPQpost:
3177 case AArch64::STPQpre:
3178 case AArch64::STPSpost:
3179 case AArch64::STPSpre:
3180 case AArch64::STPWpost:
3181 case AArch64::STPWpre:
3182 case AArch64::STPXpost:
3183 case AArch64::STPXpre: {
3184 unsigned Rt = Inst.getOperand(1).getReg();
3185 unsigned Rt2 = Inst.getOperand(2).getReg();
3186 unsigned Rn = Inst.getOperand(3).getReg();
3187 if (RI->isSubRegisterEq(Rn, Rt))
3188 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3189 "is also a source");
3190 if (RI->isSubRegisterEq(Rn, Rt2))
3191 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3192 "is also a source");
3193 break;
3194 }
3195 case AArch64::LDRBBpre:
3196 case AArch64::LDRBpre:
3197 case AArch64::LDRHHpre:
3198 case AArch64::LDRHpre:
3199 case AArch64::LDRSBWpre:
3200 case AArch64::LDRSBXpre:
3201 case AArch64::LDRSHWpre:
3202 case AArch64::LDRSHXpre:
3203 case AArch64::LDRSWpre:
3204 case AArch64::LDRWpre:
3205 case AArch64::LDRXpre:
3206 case AArch64::LDRBBpost:
3207 case AArch64::LDRBpost:
3208 case AArch64::LDRHHpost:
3209 case AArch64::LDRHpost:
3210 case AArch64::LDRSBWpost:
3211 case AArch64::LDRSBXpost:
3212 case AArch64::LDRSHWpost:
3213 case AArch64::LDRSHXpost:
3214 case AArch64::LDRSWpost:
3215 case AArch64::LDRWpost:
3216 case AArch64::LDRXpost: {
3217 unsigned Rt = Inst.getOperand(1).getReg();
3218 unsigned Rn = Inst.getOperand(2).getReg();
3219 if (RI->isSubRegisterEq(Rn, Rt))
3220 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3221 "is also a source");
3222 break;
3223 }
3224 case AArch64::STRBBpost:
3225 case AArch64::STRBpost:
3226 case AArch64::STRHHpost:
3227 case AArch64::STRHpost:
3228 case AArch64::STRWpost:
3229 case AArch64::STRXpost:
3230 case AArch64::STRBBpre:
3231 case AArch64::STRBpre:
3232 case AArch64::STRHHpre:
3233 case AArch64::STRHpre:
3234 case AArch64::STRWpre:
3235 case AArch64::STRXpre: {
3236 unsigned Rt = Inst.getOperand(1).getReg();
3237 unsigned Rn = Inst.getOperand(2).getReg();
3238 if (RI->isSubRegisterEq(Rn, Rt))
3239 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3240 "is also a source");
3241 break;
3242 }
3243 }
3244
3245 // Now check immediate ranges. Separate from the above as there is overlap
3246 // in the instructions being checked and this keeps the nested conditionals
3247 // to a minimum.
3248 switch (Inst.getOpcode()) {
3249 case AArch64::ADDSWri:
3250 case AArch64::ADDSXri:
3251 case AArch64::ADDWri:
3252 case AArch64::ADDXri:
3253 case AArch64::SUBSWri:
3254 case AArch64::SUBSXri:
3255 case AArch64::SUBWri:
3256 case AArch64::SUBXri: {
3257 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3258 // some slight duplication here.
3259 if (Inst.getOperand(2).isExpr()) {
3260 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3261 AArch64MCExpr::VariantKind ELFRefKind;
3262 MCSymbolRefExpr::VariantKind DarwinRefKind;
3263 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003264 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3265
3266 // Only allow these with ADDXri.
3267 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3268 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3269 Inst.getOpcode() == AArch64::ADDXri)
3270 return false;
3271
3272 // Only allow these with ADDXri/ADDWri
3273 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3274 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3275 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3276 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3277 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3278 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3279 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3280 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3281 (Inst.getOpcode() == AArch64::ADDXri ||
3282 Inst.getOpcode() == AArch64::ADDWri))
3283 return false;
3284
3285 // Don't allow symbol refs in the immediate field otherwise
3286 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3287 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3288 // 'cmp w0, 'borked')
3289 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003290 }
Diana Picusc93518d2016-10-11 09:17:47 +00003291 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003292 }
3293 return false;
3294 }
3295 default:
3296 return false;
3297 }
3298}
3299
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003300std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS);
3301
3302bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3303 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003304 switch (ErrCode) {
3305 case Match_MissingFeature:
3306 return Error(Loc,
3307 "instruction requires a CPU feature not currently enabled");
3308 case Match_InvalidOperand:
3309 return Error(Loc, "invalid operand for instruction");
3310 case Match_InvalidSuffix:
3311 return Error(Loc, "invalid type suffix for instruction");
3312 case Match_InvalidCondCode:
3313 return Error(Loc, "expected AArch64 condition code");
3314 case Match_AddSubRegExtendSmall:
3315 return Error(Loc,
3316 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3317 case Match_AddSubRegExtendLarge:
3318 return Error(Loc,
3319 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3320 case Match_AddSubSecondSource:
3321 return Error(Loc,
3322 "expected compatible register, symbol or integer in range [0, 4095]");
3323 case Match_LogicalSecondSource:
3324 return Error(Loc, "expected compatible register or logical immediate");
3325 case Match_InvalidMovImm32Shift:
3326 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3327 case Match_InvalidMovImm64Shift:
3328 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3329 case Match_AddSubRegShift32:
3330 return Error(Loc,
3331 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3332 case Match_AddSubRegShift64:
3333 return Error(Loc,
3334 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3335 case Match_InvalidFPImm:
3336 return Error(Loc,
3337 "expected compatible register or floating-point constant");
3338 case Match_InvalidMemoryIndexedSImm9:
3339 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003340 case Match_InvalidMemoryIndexedSImm10:
3341 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003342 case Match_InvalidMemoryIndexed4SImm7:
3343 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3344 case Match_InvalidMemoryIndexed8SImm7:
3345 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3346 case Match_InvalidMemoryIndexed16SImm7:
3347 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3348 case Match_InvalidMemoryWExtend8:
3349 return Error(Loc,
3350 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3351 case Match_InvalidMemoryWExtend16:
3352 return Error(Loc,
3353 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3354 case Match_InvalidMemoryWExtend32:
3355 return Error(Loc,
3356 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3357 case Match_InvalidMemoryWExtend64:
3358 return Error(Loc,
3359 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3360 case Match_InvalidMemoryWExtend128:
3361 return Error(Loc,
3362 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3363 case Match_InvalidMemoryXExtend8:
3364 return Error(Loc,
3365 "expected 'lsl' or 'sxtx' with optional shift of #0");
3366 case Match_InvalidMemoryXExtend16:
3367 return Error(Loc,
3368 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3369 case Match_InvalidMemoryXExtend32:
3370 return Error(Loc,
3371 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3372 case Match_InvalidMemoryXExtend64:
3373 return Error(Loc,
3374 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3375 case Match_InvalidMemoryXExtend128:
3376 return Error(Loc,
3377 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3378 case Match_InvalidMemoryIndexed1:
3379 return Error(Loc, "index must be an integer in range [0, 4095].");
3380 case Match_InvalidMemoryIndexed2:
3381 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3382 case Match_InvalidMemoryIndexed4:
3383 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3384 case Match_InvalidMemoryIndexed8:
3385 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3386 case Match_InvalidMemoryIndexed16:
3387 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003388 case Match_InvalidImm0_1:
3389 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003390 case Match_InvalidImm0_7:
3391 return Error(Loc, "immediate must be an integer in range [0, 7].");
3392 case Match_InvalidImm0_15:
3393 return Error(Loc, "immediate must be an integer in range [0, 15].");
3394 case Match_InvalidImm0_31:
3395 return Error(Loc, "immediate must be an integer in range [0, 31].");
3396 case Match_InvalidImm0_63:
3397 return Error(Loc, "immediate must be an integer in range [0, 63].");
3398 case Match_InvalidImm0_127:
3399 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003400 case Match_InvalidImm0_255:
3401 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003402 case Match_InvalidImm0_65535:
3403 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3404 case Match_InvalidImm1_8:
3405 return Error(Loc, "immediate must be an integer in range [1, 8].");
3406 case Match_InvalidImm1_16:
3407 return Error(Loc, "immediate must be an integer in range [1, 16].");
3408 case Match_InvalidImm1_32:
3409 return Error(Loc, "immediate must be an integer in range [1, 32].");
3410 case Match_InvalidImm1_64:
3411 return Error(Loc, "immediate must be an integer in range [1, 64].");
3412 case Match_InvalidIndex1:
3413 return Error(Loc, "expected lane specifier '[1]'");
3414 case Match_InvalidIndexB:
3415 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3416 case Match_InvalidIndexH:
3417 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3418 case Match_InvalidIndexS:
3419 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3420 case Match_InvalidIndexD:
3421 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3422 case Match_InvalidLabel:
3423 return Error(Loc, "expected label or encodable integer pc offset");
3424 case Match_MRS:
3425 return Error(Loc, "expected readable system register");
3426 case Match_MSR:
3427 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003428 case Match_InvalidComplexRotationEven:
3429 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3430 case Match_InvalidComplexRotationOdd:
3431 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003432 case Match_MnemonicFail: {
3433 std::string Suggestion = AArch64MnemonicSpellCheck(
3434 ((AArch64Operand &)*Operands[0]).getToken(),
3435 ComputeAvailableFeatures(STI->getFeatureBits()));
3436 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3437 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003438 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003439 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003440 }
3441}
3442
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003443static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003444
3445bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3446 OperandVector &Operands,
3447 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003448 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003449 bool MatchingInlineAsm) {
3450 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003451 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3452 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003453
David Blaikie960ea3f2014-06-08 16:18:35 +00003454 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003455 unsigned NumOperands = Operands.size();
3456
3457 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003458 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3459 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3460 if (Op2.isReg() && Op3.isImm()) {
3461 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003462 if (Op3CE) {
3463 uint64_t Op3Val = Op3CE->getValue();
3464 uint64_t NewOp3Val = 0;
3465 uint64_t NewOp4Val = 0;
3466 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003467 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003468 NewOp3Val = (32 - Op3Val) & 0x1f;
3469 NewOp4Val = 31 - Op3Val;
3470 } else {
3471 NewOp3Val = (64 - Op3Val) & 0x3f;
3472 NewOp4Val = 63 - Op3Val;
3473 }
3474
Jim Grosbach13760bd2015-05-30 01:25:56 +00003475 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3476 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003477
3478 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003479 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003480 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003481 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3482 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3483 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003484 }
3485 }
Tim Northover03b99f62015-04-30 18:28:58 +00003486 } else if (NumOperands == 4 && Tok == "bfc") {
3487 // FIXME: Horrible hack to handle BFC->BFM alias.
3488 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3489 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3490 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3491
3492 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3493 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3494 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3495
3496 if (LSBCE && WidthCE) {
3497 uint64_t LSB = LSBCE->getValue();
3498 uint64_t Width = WidthCE->getValue();
3499
3500 uint64_t RegWidth = 0;
3501 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3502 Op1.getReg()))
3503 RegWidth = 64;
3504 else
3505 RegWidth = 32;
3506
3507 if (LSB >= RegWidth)
3508 return Error(LSBOp.getStartLoc(),
3509 "expected integer in range [0, 31]");
3510 if (Width < 1 || Width > RegWidth)
3511 return Error(WidthOp.getStartLoc(),
3512 "expected integer in range [1, 32]");
3513
3514 uint64_t ImmR = 0;
3515 if (RegWidth == 32)
3516 ImmR = (32 - LSB) & 0x1f;
3517 else
3518 ImmR = (64 - LSB) & 0x3f;
3519
3520 uint64_t ImmS = Width - 1;
3521
3522 if (ImmR != 0 && ImmS >= ImmR)
3523 return Error(WidthOp.getStartLoc(),
3524 "requested insert overflows register");
3525
Jim Grosbach13760bd2015-05-30 01:25:56 +00003526 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3527 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003528 Operands[0] = AArch64Operand::CreateToken(
3529 "bfm", false, Op.getStartLoc(), getContext());
3530 Operands[2] = AArch64Operand::CreateReg(
3531 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3532 SMLoc(), getContext());
3533 Operands[3] = AArch64Operand::CreateImm(
3534 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3535 Operands.emplace_back(
3536 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3537 WidthOp.getEndLoc(), getContext()));
3538 }
3539 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003540 } else if (NumOperands == 5) {
3541 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3542 // UBFIZ -> UBFM aliases.
3543 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003544 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3545 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3546 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003547
David Blaikie960ea3f2014-06-08 16:18:35 +00003548 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3549 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3550 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003551
3552 if (Op3CE && Op4CE) {
3553 uint64_t Op3Val = Op3CE->getValue();
3554 uint64_t Op4Val = Op4CE->getValue();
3555
3556 uint64_t RegWidth = 0;
3557 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003558 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003559 RegWidth = 64;
3560 else
3561 RegWidth = 32;
3562
3563 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003564 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003565 "expected integer in range [0, 31]");
3566 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003567 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003568 "expected integer in range [1, 32]");
3569
3570 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003571 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003572 NewOp3Val = (32 - Op3Val) & 0x1f;
3573 else
3574 NewOp3Val = (64 - Op3Val) & 0x3f;
3575
3576 uint64_t NewOp4Val = Op4Val - 1;
3577
3578 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003579 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003580 "requested insert overflows register");
3581
3582 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003583 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003584 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003585 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003586 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003587 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003588 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003589 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003590 if (Tok == "bfi")
3591 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003592 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003593 else if (Tok == "sbfiz")
3594 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003595 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003596 else if (Tok == "ubfiz")
3597 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003598 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003599 else
3600 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003601 }
3602 }
3603
3604 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3605 // UBFX -> UBFM aliases.
3606 } else if (NumOperands == 5 &&
3607 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003608 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3609 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3610 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003611
David Blaikie960ea3f2014-06-08 16:18:35 +00003612 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3613 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3614 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003615
3616 if (Op3CE && Op4CE) {
3617 uint64_t Op3Val = Op3CE->getValue();
3618 uint64_t Op4Val = Op4CE->getValue();
3619
3620 uint64_t RegWidth = 0;
3621 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003622 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003623 RegWidth = 64;
3624 else
3625 RegWidth = 32;
3626
3627 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003628 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003629 "expected integer in range [0, 31]");
3630 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003631 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003632 "expected integer in range [1, 32]");
3633
3634 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3635
3636 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003637 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003638 "requested extract overflows register");
3639
3640 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003641 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003642 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003643 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003644 if (Tok == "bfxil")
3645 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003646 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003647 else if (Tok == "sbfx")
3648 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003649 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003650 else if (Tok == "ubfx")
3651 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003652 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003653 else
3654 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003655 }
3656 }
3657 }
3658 }
3659 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3660 // InstAlias can't quite handle this since the reg classes aren't
3661 // subclasses.
3662 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3663 // The source register can be Wn here, but the matcher expects a
3664 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003665 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3666 if (Op.isReg()) {
3667 unsigned Reg = getXRegFromWReg(Op.getReg());
3668 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3669 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003670 }
3671 }
3672 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3673 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003674 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3675 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003676 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003677 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003678 // The source register can be Wn here, but the matcher expects a
3679 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003680 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3681 if (Op.isReg()) {
3682 unsigned Reg = getXRegFromWReg(Op.getReg());
3683 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3684 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003685 }
3686 }
3687 }
3688 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3689 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003690 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3691 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003692 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003693 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003694 // The source register can be Wn here, but the matcher expects a
3695 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003696 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3697 if (Op.isReg()) {
3698 unsigned Reg = getWRegFromXReg(Op.getReg());
3699 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3700 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003701 }
3702 }
3703 }
3704
Tim Northover3b0846e2014-05-24 12:50:23 +00003705 MCInst Inst;
3706 // First try to match against the secondary set of tables containing the
3707 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3708 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003709 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003710
3711 // If that fails, try against the alternate table containing long-form NEON:
3712 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003713 if (MatchResult != Match_Success) {
3714 // But first, save the short-form match result: we can use it in case the
3715 // long-form match also fails.
3716 auto ShortFormNEONErrorInfo = ErrorInfo;
3717 auto ShortFormNEONMatchResult = MatchResult;
3718
Tim Northover3b0846e2014-05-24 12:50:23 +00003719 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003720 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003721
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003722 // Now, both matches failed, and the long-form match failed on the mnemonic
3723 // suffix token operand. The short-form match failure is probably more
3724 // relevant: use it instead.
3725 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003726 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003727 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3728 MatchResult = ShortFormNEONMatchResult;
3729 ErrorInfo = ShortFormNEONErrorInfo;
3730 }
3731 }
3732
Tim Northover3b0846e2014-05-24 12:50:23 +00003733 switch (MatchResult) {
3734 case Match_Success: {
3735 // Perform range checking and other semantic validations
3736 SmallVector<SMLoc, 8> OperandLocs;
3737 NumOperands = Operands.size();
3738 for (unsigned i = 1; i < NumOperands; ++i)
3739 OperandLocs.push_back(Operands[i]->getStartLoc());
3740 if (validateInstruction(Inst, OperandLocs))
3741 return true;
3742
3743 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003744 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003745 return false;
3746 }
3747 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003748 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003749 // Special case the error message for the very common case where only
3750 // a single subtarget feature is missing (neon, e.g.).
3751 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003752 uint64_t Mask = 1;
3753 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3754 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003755 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003756 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003757 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003758 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003759 }
3760 return Error(IDLoc, Msg);
3761 }
3762 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003763 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003764 case Match_InvalidOperand: {
3765 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003766
Tim Northover26bb14e2014-08-18 11:49:42 +00003767 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003768 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003769 return Error(IDLoc, "too few operands for instruction",
3770 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003771
David Blaikie960ea3f2014-06-08 16:18:35 +00003772 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003773 if (ErrorLoc == SMLoc())
3774 ErrorLoc = IDLoc;
3775 }
3776 // If the match failed on a suffix token operand, tweak the diagnostic
3777 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003778 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
3779 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00003780 MatchResult = Match_InvalidSuffix;
3781
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003782 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003783 }
3784 case Match_InvalidMemoryIndexed1:
3785 case Match_InvalidMemoryIndexed2:
3786 case Match_InvalidMemoryIndexed4:
3787 case Match_InvalidMemoryIndexed8:
3788 case Match_InvalidMemoryIndexed16:
3789 case Match_InvalidCondCode:
3790 case Match_AddSubRegExtendSmall:
3791 case Match_AddSubRegExtendLarge:
3792 case Match_AddSubSecondSource:
3793 case Match_LogicalSecondSource:
3794 case Match_AddSubRegShift32:
3795 case Match_AddSubRegShift64:
3796 case Match_InvalidMovImm32Shift:
3797 case Match_InvalidMovImm64Shift:
3798 case Match_InvalidFPImm:
3799 case Match_InvalidMemoryWExtend8:
3800 case Match_InvalidMemoryWExtend16:
3801 case Match_InvalidMemoryWExtend32:
3802 case Match_InvalidMemoryWExtend64:
3803 case Match_InvalidMemoryWExtend128:
3804 case Match_InvalidMemoryXExtend8:
3805 case Match_InvalidMemoryXExtend16:
3806 case Match_InvalidMemoryXExtend32:
3807 case Match_InvalidMemoryXExtend64:
3808 case Match_InvalidMemoryXExtend128:
3809 case Match_InvalidMemoryIndexed4SImm7:
3810 case Match_InvalidMemoryIndexed8SImm7:
3811 case Match_InvalidMemoryIndexed16SImm7:
3812 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00003813 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003814 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003815 case Match_InvalidImm0_7:
3816 case Match_InvalidImm0_15:
3817 case Match_InvalidImm0_31:
3818 case Match_InvalidImm0_63:
3819 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003820 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00003821 case Match_InvalidImm0_65535:
3822 case Match_InvalidImm1_8:
3823 case Match_InvalidImm1_16:
3824 case Match_InvalidImm1_32:
3825 case Match_InvalidImm1_64:
3826 case Match_InvalidIndex1:
3827 case Match_InvalidIndexB:
3828 case Match_InvalidIndexH:
3829 case Match_InvalidIndexS:
3830 case Match_InvalidIndexD:
3831 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00003832 case Match_InvalidComplexRotationEven:
3833 case Match_InvalidComplexRotationOdd:
Tim Northover3b0846e2014-05-24 12:50:23 +00003834 case Match_MSR:
3835 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00003836 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003837 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003838 // Any time we get here, there's nothing fancy to do. Just get the
3839 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00003840 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003841 if (ErrorLoc == SMLoc())
3842 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003843 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003844 }
3845 }
3846
3847 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003848}
3849
3850/// ParseDirective parses the arm specific directives
3851bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00003852 const MCObjectFileInfo::Environment Format =
3853 getContext().getObjectFileInfo()->getObjectFileType();
3854 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
3855 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00003856
Tim Northover3b0846e2014-05-24 12:50:23 +00003857 StringRef IDVal = DirectiveID.getIdentifier();
3858 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003859 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00003860 parseDirectiveArch(Loc);
3861 else if (IDVal == ".cpu")
3862 parseDirectiveCPU(Loc);
3863 else if (IDVal == ".hword")
3864 parseDirectiveWord(2, Loc);
3865 else if (IDVal == ".word")
3866 parseDirectiveWord(4, Loc);
3867 else if (IDVal == ".xword")
3868 parseDirectiveWord(8, Loc);
3869 else if (IDVal == ".tlsdesccall")
3870 parseDirectiveTLSDescCall(Loc);
3871 else if (IDVal == ".ltorg" || IDVal == ".pool")
3872 parseDirectiveLtorg(Loc);
3873 else if (IDVal == ".unreq")
3874 parseDirectiveUnreq(Loc);
3875 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00003876 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00003877 parseDirectiveInst(Loc);
3878 else
3879 return true;
3880 } else if (IDVal == MCLOHDirectiveName())
3881 parseDirectiveLOH(IDVal, Loc);
3882 else
3883 return true;
3884 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003885}
3886
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003887static const struct {
3888 const char *Name;
3889 const FeatureBitset Features;
3890} ExtensionMap[] = {
3891 { "crc", {AArch64::FeatureCRC} },
3892 { "crypto", {AArch64::FeatureCrypto} },
3893 { "fp", {AArch64::FeatureFPARMv8} },
3894 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003895 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00003896 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003897
3898 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003899 { "pan", {} },
3900 { "lor", {} },
3901 { "rdma", {} },
3902 { "profile", {} },
3903};
3904
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003905/// parseDirectiveArch
3906/// ::= .arch token
3907bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
3908 SMLoc ArchLoc = getLoc();
3909
3910 StringRef Arch, ExtensionString;
3911 std::tie(Arch, ExtensionString) =
3912 getParser().parseStringToEndOfStatement().trim().split('+');
3913
Florian Hahn67ddd1d2017-07-27 16:27:56 +00003914 AArch64::ArchKind ID = AArch64::parseArch(Arch);
3915 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00003916 return Error(ArchLoc, "unknown arch name");
3917
3918 if (parseToken(AsmToken::EndOfStatement))
3919 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003920
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003921 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00003922 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003923 AArch64::getArchFeatures(ID, AArch64Features);
3924 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
3925 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003926
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003927 MCSubtargetInfo &STI = copySTI();
3928 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
3929 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
3930
3931 SmallVector<StringRef, 4> RequestedExtensions;
3932 if (!ExtensionString.empty())
3933 ExtensionString.split(RequestedExtensions, '+');
3934
3935 FeatureBitset Features = STI.getFeatureBits();
3936 for (auto Name : RequestedExtensions) {
3937 bool EnableFeature = true;
3938
3939 if (Name.startswith_lower("no")) {
3940 EnableFeature = false;
3941 Name = Name.substr(2);
3942 }
3943
3944 for (const auto &Extension : ExtensionMap) {
3945 if (Extension.Name != Name)
3946 continue;
3947
3948 if (Extension.Features.none())
3949 report_fatal_error("unsupported architectural extension: " + Name);
3950
3951 FeatureBitset ToggleFeatures = EnableFeature
3952 ? (~Features & Extension.Features)
3953 : ( Features & Extension.Features);
3954 uint64_t Features =
3955 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
3956 setAvailableFeatures(Features);
3957 break;
3958 }
3959 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003960 return false;
3961}
3962
Tim Northover8b96c7e2017-05-15 19:42:15 +00003963static SMLoc incrementLoc(SMLoc L, int Offset) {
3964 return SMLoc::getFromPointer(L.getPointer() + Offset);
3965}
3966
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003967/// parseDirectiveCPU
3968/// ::= .cpu id
3969bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00003970 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003971
3972 StringRef CPU, ExtensionString;
3973 std::tie(CPU, ExtensionString) =
3974 getParser().parseStringToEndOfStatement().trim().split('+');
3975
Nirav Davee833c6c2016-11-08 18:31:04 +00003976 if (parseToken(AsmToken::EndOfStatement))
3977 return true;
3978
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003979 SmallVector<StringRef, 4> RequestedExtensions;
3980 if (!ExtensionString.empty())
3981 ExtensionString.split(RequestedExtensions, '+');
3982
3983 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
3984 // once that is tablegen'ed
3985 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00003986 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003987 return false;
3988 }
3989
3990 MCSubtargetInfo &STI = copySTI();
3991 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00003992 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003993
3994 FeatureBitset Features = STI.getFeatureBits();
3995 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00003996 // Advance source location past '+'.
3997 CurLoc = incrementLoc(CurLoc, 1);
3998
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003999 bool EnableFeature = true;
4000
4001 if (Name.startswith_lower("no")) {
4002 EnableFeature = false;
4003 Name = Name.substr(2);
4004 }
4005
Tim Northover8b96c7e2017-05-15 19:42:15 +00004006 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004007 for (const auto &Extension : ExtensionMap) {
4008 if (Extension.Name != Name)
4009 continue;
4010
4011 if (Extension.Features.none())
4012 report_fatal_error("unsupported architectural extension: " + Name);
4013
4014 FeatureBitset ToggleFeatures = EnableFeature
4015 ? (~Features & Extension.Features)
4016 : ( Features & Extension.Features);
4017 uint64_t Features =
4018 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4019 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004020 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004021
4022 break;
4023 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004024
4025 if (!FoundExtension)
4026 Error(CurLoc, "unsupported architectural extension");
4027
4028 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004029 }
4030 return false;
4031}
4032
Tim Northover3b0846e2014-05-24 12:50:23 +00004033/// parseDirectiveWord
4034/// ::= .word [ expression (, expression)* ]
4035bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004036 auto parseOp = [&]() -> bool {
4037 const MCExpr *Value;
4038 if (getParser().parseExpression(Value))
4039 return true;
4040 getParser().getStreamer().EmitValue(Value, Size, L);
4041 return false;
4042 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004043
Nirav Davee833c6c2016-11-08 18:31:04 +00004044 if (parseMany(parseOp))
4045 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004046 return false;
4047}
4048
Chad Rosierdcd2a302014-10-22 20:35:57 +00004049/// parseDirectiveInst
4050/// ::= .inst opcode [, ...]
4051bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004052 if (getLexer().is(AsmToken::EndOfStatement))
4053 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004054
Nirav Davee833c6c2016-11-08 18:31:04 +00004055 auto parseOp = [&]() -> bool {
4056 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004057 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004058 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4059 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004060 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004061 if (check(!Value, L, "expected constant expression"))
4062 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004063 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004064 return false;
4065 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004066
Nirav Davee833c6c2016-11-08 18:31:04 +00004067 if (parseMany(parseOp))
4068 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004069 return false;
4070}
4071
Tim Northover3b0846e2014-05-24 12:50:23 +00004072// parseDirectiveTLSDescCall:
4073// ::= .tlsdesccall symbol
4074bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4075 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004076 if (check(getParser().parseIdentifier(Name), L,
4077 "expected symbol after directive") ||
4078 parseToken(AsmToken::EndOfStatement))
4079 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004080
Jim Grosbach6f482002015-05-18 18:43:14 +00004081 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004082 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4083 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004084
4085 MCInst Inst;
4086 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004087 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004088
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004089 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004090 return false;
4091}
4092
4093/// ::= .loh <lohName | lohId> label1, ..., labelN
4094/// The number of arguments depends on the loh identifier.
4095bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004096 MCLOHType Kind;
4097 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4098 if (getParser().getTok().isNot(AsmToken::Integer))
4099 return TokError("expected an identifier or a number in directive");
4100 // We successfully get a numeric value for the identifier.
4101 // Check if it is valid.
4102 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004103 if (Id <= -1U && !isValidMCLOHType(Id))
4104 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004105 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004106 } else {
4107 StringRef Name = getTok().getIdentifier();
4108 // We successfully parse an identifier.
4109 // Check if it is a recognized one.
4110 int Id = MCLOHNameToId(Name);
4111
4112 if (Id == -1)
4113 return TokError("invalid identifier in directive");
4114 Kind = (MCLOHType)Id;
4115 }
4116 // Consume the identifier.
4117 Lex();
4118 // Get the number of arguments of this LOH.
4119 int NbArgs = MCLOHIdToNbArgs(Kind);
4120
4121 assert(NbArgs != -1 && "Invalid number of arguments");
4122
4123 SmallVector<MCSymbol *, 3> Args;
4124 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4125 StringRef Name;
4126 if (getParser().parseIdentifier(Name))
4127 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004128 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004129
4130 if (Idx + 1 == NbArgs)
4131 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004132 if (parseToken(AsmToken::Comma,
4133 "unexpected token in '" + Twine(IDVal) + "' directive"))
4134 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004135 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004136 if (parseToken(AsmToken::EndOfStatement,
4137 "unexpected token in '" + Twine(IDVal) + "' directive"))
4138 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004139
4140 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4141 return false;
4142}
4143
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004144/// parseDirectiveLtorg
4145/// ::= .ltorg | .pool
4146bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004147 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4148 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004149 getTargetStreamer().emitCurrentConstantPool();
4150 return false;
4151}
4152
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004153/// parseDirectiveReq
4154/// ::= name .req registername
4155bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004156 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004157 Parser.Lex(); // Eat the '.req' token.
4158 SMLoc SRegLoc = getLoc();
4159 unsigned RegNum = tryParseRegister();
4160 bool IsVector = false;
4161
4162 if (RegNum == static_cast<unsigned>(-1)) {
4163 StringRef Kind;
4164 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004165 if (!Kind.empty())
4166 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004167 IsVector = true;
4168 }
4169
Nirav Dave2364748a2016-09-16 18:30:20 +00004170 if (RegNum == static_cast<unsigned>(-1))
4171 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004172
4173 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004174 if (parseToken(AsmToken::EndOfStatement,
4175 "unexpected input in .req directive"))
4176 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004177
4178 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004179 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004180 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4181
Nirav Dave2364748a2016-09-16 18:30:20 +00004182 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004183}
4184
4185/// parseDirectiveUneq
4186/// ::= .unreq registername
4187bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004188 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004189 if (getTok().isNot(AsmToken::Identifier))
4190 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004191 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4192 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004193 if (parseToken(AsmToken::EndOfStatement))
4194 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004195 return false;
4196}
4197
Tim Northover3b0846e2014-05-24 12:50:23 +00004198bool
4199AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4200 AArch64MCExpr::VariantKind &ELFRefKind,
4201 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4202 int64_t &Addend) {
4203 ELFRefKind = AArch64MCExpr::VK_INVALID;
4204 DarwinRefKind = MCSymbolRefExpr::VK_None;
4205 Addend = 0;
4206
4207 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4208 ELFRefKind = AE->getKind();
4209 Expr = AE->getSubExpr();
4210 }
4211
4212 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4213 if (SE) {
4214 // It's a simple symbol reference with no addend.
4215 DarwinRefKind = SE->getKind();
4216 return true;
4217 }
4218
4219 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4220 if (!BE)
4221 return false;
4222
4223 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4224 if (!SE)
4225 return false;
4226 DarwinRefKind = SE->getKind();
4227
4228 if (BE->getOpcode() != MCBinaryExpr::Add &&
4229 BE->getOpcode() != MCBinaryExpr::Sub)
4230 return false;
4231
4232 // See if the addend is is a constant, otherwise there's more going
4233 // on here than we can deal with.
4234 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4235 if (!AddendExpr)
4236 return false;
4237
4238 Addend = AddendExpr->getValue();
4239 if (BE->getOpcode() == MCBinaryExpr::Sub)
4240 Addend = -Addend;
4241
4242 // It's some symbol reference + a constant addend, but really
4243 // shouldn't use both Darwin and ELF syntax.
4244 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4245 DarwinRefKind == MCSymbolRefExpr::VK_None;
4246}
4247
4248/// Force static initialization.
4249extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004250 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4251 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4252 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004253}
4254
4255#define GET_REGISTER_MATCHER
4256#define GET_SUBTARGET_FEATURE_NAME
4257#define GET_MATCHER_IMPLEMENTATION
4258#include "AArch64GenAsmMatcher.inc"
4259
4260// Define this matcher function after the auto-generated include so we
4261// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004262unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004263 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004264 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004265 // If the kind is a token for a literal immediate, check if our asm
4266 // operand matches. This is for InstAliases which have a fixed-value
4267 // immediate in the syntax.
4268 int64_t ExpectedVal;
4269 switch (Kind) {
4270 default:
4271 return Match_InvalidOperand;
4272 case MCK__35_0:
4273 ExpectedVal = 0;
4274 break;
4275 case MCK__35_1:
4276 ExpectedVal = 1;
4277 break;
4278 case MCK__35_12:
4279 ExpectedVal = 12;
4280 break;
4281 case MCK__35_16:
4282 ExpectedVal = 16;
4283 break;
4284 case MCK__35_2:
4285 ExpectedVal = 2;
4286 break;
4287 case MCK__35_24:
4288 ExpectedVal = 24;
4289 break;
4290 case MCK__35_3:
4291 ExpectedVal = 3;
4292 break;
4293 case MCK__35_32:
4294 ExpectedVal = 32;
4295 break;
4296 case MCK__35_4:
4297 ExpectedVal = 4;
4298 break;
4299 case MCK__35_48:
4300 ExpectedVal = 48;
4301 break;
4302 case MCK__35_6:
4303 ExpectedVal = 6;
4304 break;
4305 case MCK__35_64:
4306 ExpectedVal = 64;
4307 break;
4308 case MCK__35_8:
4309 ExpectedVal = 8;
4310 break;
4311 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004312 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004313 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004314 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004315 if (!CE)
4316 return Match_InvalidOperand;
4317 if (CE->getValue() == ExpectedVal)
4318 return Match_Success;
4319 return Match_InvalidOperand;
4320}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004321
Alex Bradbury58eba092016-11-01 16:32:05 +00004322OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004323AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4324
4325 SMLoc S = getLoc();
4326
4327 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4328 Error(S, "expected register");
4329 return MatchOperand_ParseFail;
4330 }
4331
4332 int FirstReg = tryParseRegister();
4333 if (FirstReg == -1) {
4334 return MatchOperand_ParseFail;
4335 }
4336 const MCRegisterClass &WRegClass =
4337 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4338 const MCRegisterClass &XRegClass =
4339 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4340
4341 bool isXReg = XRegClass.contains(FirstReg),
4342 isWReg = WRegClass.contains(FirstReg);
4343 if (!isXReg && !isWReg) {
4344 Error(S, "expected first even register of a "
4345 "consecutive same-size even/odd register pair");
4346 return MatchOperand_ParseFail;
4347 }
4348
4349 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4350 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4351
4352 if (FirstEncoding & 0x1) {
4353 Error(S, "expected first even register of a "
4354 "consecutive same-size even/odd register pair");
4355 return MatchOperand_ParseFail;
4356 }
4357
4358 SMLoc M = getLoc();
4359 if (getParser().getTok().isNot(AsmToken::Comma)) {
4360 Error(M, "expected comma");
4361 return MatchOperand_ParseFail;
4362 }
4363 // Eat the comma
4364 getParser().Lex();
4365
4366 SMLoc E = getLoc();
4367 int SecondReg = tryParseRegister();
4368 if (SecondReg ==-1) {
4369 return MatchOperand_ParseFail;
4370 }
4371
Eugene Zelenko049b0172017-01-06 00:30:53 +00004372 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004373 (isXReg && !XRegClass.contains(SecondReg)) ||
4374 (isWReg && !WRegClass.contains(SecondReg))) {
4375 Error(E,"expected second odd register of a "
4376 "consecutive same-size even/odd register pair");
4377 return MatchOperand_ParseFail;
4378 }
Joel Jones504bf332016-10-24 13:37:13 +00004379
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004380 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004381 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004382 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4383 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4384 } else {
4385 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4386 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4387 }
4388
4389 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4390 getContext()));
4391
4392 return MatchOperand_Success;
4393}