blob: 3ed3c880631d436dc2c3a8dbfd3de9e1cb32ef31 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000019#include "llvm/ADT/STLExtras.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Tim Northover3b0846e2014-05-24 12:50:23 +000062class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000063private:
64 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000065
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000066 // Map of register aliases registers via the .req directive.
Eugene Zelenko049b0172017-01-06 00:30:53 +000067 StringMap<std::pair<bool, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000068
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000069 AArch64TargetStreamer &getTargetStreamer() {
70 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
71 return static_cast<AArch64TargetStreamer &>(TS);
72 }
73
Rafael Espindola961d4692014-11-11 05:18:41 +000074 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000075
76 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
77 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
78 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000079 unsigned matchRegisterNameAlias(StringRef Name, bool isVector);
Tim Northover3b0846e2014-05-24 12:50:23 +000080 int tryParseRegister();
81 int tryMatchVectorRegister(StringRef &Kind, bool expected);
82 bool parseRegister(OperandVector &Operands);
83 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
84 bool parseVectorList(OperandVector &Operands);
85 bool parseOperand(OperandVector &Operands, bool isCondCode,
86 bool invertCondCode);
87
Tim Northover3b0846e2014-05-24 12:50:23 +000088 bool showMatchError(SMLoc Loc, unsigned ErrCode);
89
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000090 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000091 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000093 bool parseDirectiveInst(SMLoc L);
94
Tim Northover3b0846e2014-05-24 12:50:23 +000095 bool parseDirectiveTLSDescCall(SMLoc L);
96
97 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000098 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000099
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000100 bool parseDirectiveReq(StringRef Name, SMLoc L);
101 bool parseDirectiveUnreq(SMLoc L);
102
Tim Northover3b0846e2014-05-24 12:50:23 +0000103 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
104 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
105 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000106 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000107 bool MatchingInlineAsm) override;
108/// @name Auto-generated Match Functions
109/// {
110
111#define GET_ASSEMBLER_HEADER
112#include "AArch64GenAsmMatcher.inc"
113
114 /// }
115
116 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
117 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
118 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
119 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
120 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
121 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000122 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000123 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
124 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
125 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
126 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
127 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
128 bool tryParseVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000129 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000130
131public:
132 enum AArch64MatchResultTy {
133 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
134#define GET_OPERAND_DIAGNOSTIC_TYPES
135#include "AArch64GenAsmMatcher.inc"
136 };
Joel Jones504bf332016-10-24 13:37:13 +0000137 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000138
Akira Hatanakab11ef082015-11-14 06:35:56 +0000139 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000140 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000141 : MCTargetAsmParser(Options, STI) {
Joel Jones504bf332016-10-24 13:37:13 +0000142 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000143 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000144 MCStreamer &S = getParser().getStreamer();
145 if (S.getTargetStreamer() == nullptr)
146 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000147
148 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000149 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000150 }
151
152 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
153 SMLoc NameLoc, OperandVector &Operands) override;
154 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
155 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000156 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000157 unsigned Kind) override;
158
159 static bool classifySymbolRef(const MCExpr *Expr,
160 AArch64MCExpr::VariantKind &ELFRefKind,
161 MCSymbolRefExpr::VariantKind &DarwinRefKind,
162 int64_t &Addend);
163};
Tim Northover3b0846e2014-05-24 12:50:23 +0000164
165/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
166/// instruction.
167class AArch64Operand : public MCParsedAsmOperand {
168private:
169 enum KindTy {
170 k_Immediate,
171 k_ShiftedImm,
172 k_CondCode,
173 k_Register,
174 k_VectorList,
175 k_VectorIndex,
176 k_Token,
177 k_SysReg,
178 k_SysCR,
179 k_Prefetch,
180 k_ShiftExtend,
181 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000182 k_Barrier,
183 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 } Kind;
185
186 SMLoc StartLoc, EndLoc;
187
188 struct TokOp {
189 const char *Data;
190 unsigned Length;
191 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
192 };
193
194 struct RegOp {
195 unsigned RegNum;
196 bool isVector;
197 };
198
199 struct VectorListOp {
200 unsigned RegNum;
201 unsigned Count;
202 unsigned NumElements;
203 unsigned ElementKind;
204 };
205
206 struct VectorIndexOp {
207 unsigned Val;
208 };
209
210 struct ImmOp {
211 const MCExpr *Val;
212 };
213
214 struct ShiftedImmOp {
215 const MCExpr *Val;
216 unsigned ShiftAmount;
217 };
218
219 struct CondCodeOp {
220 AArch64CC::CondCode Code;
221 };
222
223 struct FPImmOp {
224 unsigned Val; // Encoded 8-bit representation.
225 };
226
227 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000228 const char *Data;
229 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000230 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000231 };
232
233 struct SysRegOp {
234 const char *Data;
235 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000236 uint32_t MRSReg;
237 uint32_t MSRReg;
238 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000239 };
240
241 struct SysCRImmOp {
242 unsigned Val;
243 };
244
245 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000246 const char *Data;
247 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000248 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000249 };
250
Oliver Stannarda34e4702015-12-01 10:48:51 +0000251 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000252 const char *Data;
253 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000254 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000255 };
256
Tim Northover3b0846e2014-05-24 12:50:23 +0000257 struct ShiftExtendOp {
258 AArch64_AM::ShiftExtendType Type;
259 unsigned Amount;
260 bool HasExplicitAmount;
261 };
262
263 struct ExtendOp {
264 unsigned Val;
265 };
266
267 union {
268 struct TokOp Tok;
269 struct RegOp Reg;
270 struct VectorListOp VectorList;
271 struct VectorIndexOp VectorIndex;
272 struct ImmOp Imm;
273 struct ShiftedImmOp ShiftedImm;
274 struct CondCodeOp CondCode;
275 struct FPImmOp FPImm;
276 struct BarrierOp Barrier;
277 struct SysRegOp SysReg;
278 struct SysCRImmOp SysCRImm;
279 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000280 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000281 struct ShiftExtendOp ShiftExtend;
282 };
283
284 // Keep the MCContext around as the MCExprs may need manipulated during
285 // the add<>Operands() calls.
286 MCContext &Ctx;
287
David Blaikie960ea3f2014-06-08 16:18:35 +0000288public:
David Blaikie9f380a32015-03-16 18:06:57 +0000289 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000290
Tim Northover3b0846e2014-05-24 12:50:23 +0000291 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
292 Kind = o.Kind;
293 StartLoc = o.StartLoc;
294 EndLoc = o.EndLoc;
295 switch (Kind) {
296 case k_Token:
297 Tok = o.Tok;
298 break;
299 case k_Immediate:
300 Imm = o.Imm;
301 break;
302 case k_ShiftedImm:
303 ShiftedImm = o.ShiftedImm;
304 break;
305 case k_CondCode:
306 CondCode = o.CondCode;
307 break;
308 case k_FPImm:
309 FPImm = o.FPImm;
310 break;
311 case k_Barrier:
312 Barrier = o.Barrier;
313 break;
314 case k_Register:
315 Reg = o.Reg;
316 break;
317 case k_VectorList:
318 VectorList = o.VectorList;
319 break;
320 case k_VectorIndex:
321 VectorIndex = o.VectorIndex;
322 break;
323 case k_SysReg:
324 SysReg = o.SysReg;
325 break;
326 case k_SysCR:
327 SysCRImm = o.SysCRImm;
328 break;
329 case k_Prefetch:
330 Prefetch = o.Prefetch;
331 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000332 case k_PSBHint:
333 PSBHint = o.PSBHint;
334 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000335 case k_ShiftExtend:
336 ShiftExtend = o.ShiftExtend;
337 break;
338 }
339 }
340
341 /// getStartLoc - Get the location of the first token of this operand.
342 SMLoc getStartLoc() const override { return StartLoc; }
343 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000344 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000345
346 StringRef getToken() const {
347 assert(Kind == k_Token && "Invalid access!");
348 return StringRef(Tok.Data, Tok.Length);
349 }
350
351 bool isTokenSuffix() const {
352 assert(Kind == k_Token && "Invalid access!");
353 return Tok.IsSuffix;
354 }
355
356 const MCExpr *getImm() const {
357 assert(Kind == k_Immediate && "Invalid access!");
358 return Imm.Val;
359 }
360
361 const MCExpr *getShiftedImmVal() const {
362 assert(Kind == k_ShiftedImm && "Invalid access!");
363 return ShiftedImm.Val;
364 }
365
366 unsigned getShiftedImmShift() const {
367 assert(Kind == k_ShiftedImm && "Invalid access!");
368 return ShiftedImm.ShiftAmount;
369 }
370
371 AArch64CC::CondCode getCondCode() const {
372 assert(Kind == k_CondCode && "Invalid access!");
373 return CondCode.Code;
374 }
375
376 unsigned getFPImm() const {
377 assert(Kind == k_FPImm && "Invalid access!");
378 return FPImm.Val;
379 }
380
381 unsigned getBarrier() const {
382 assert(Kind == k_Barrier && "Invalid access!");
383 return Barrier.Val;
384 }
385
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000386 StringRef getBarrierName() const {
387 assert(Kind == k_Barrier && "Invalid access!");
388 return StringRef(Barrier.Data, Barrier.Length);
389 }
390
Tim Northover3b0846e2014-05-24 12:50:23 +0000391 unsigned getReg() const override {
392 assert(Kind == k_Register && "Invalid access!");
393 return Reg.RegNum;
394 }
395
396 unsigned getVectorListStart() const {
397 assert(Kind == k_VectorList && "Invalid access!");
398 return VectorList.RegNum;
399 }
400
401 unsigned getVectorListCount() const {
402 assert(Kind == k_VectorList && "Invalid access!");
403 return VectorList.Count;
404 }
405
406 unsigned getVectorIndex() const {
407 assert(Kind == k_VectorIndex && "Invalid access!");
408 return VectorIndex.Val;
409 }
410
411 StringRef getSysReg() const {
412 assert(Kind == k_SysReg && "Invalid access!");
413 return StringRef(SysReg.Data, SysReg.Length);
414 }
415
Tim Northover3b0846e2014-05-24 12:50:23 +0000416 unsigned getSysCR() const {
417 assert(Kind == k_SysCR && "Invalid access!");
418 return SysCRImm.Val;
419 }
420
421 unsigned getPrefetch() const {
422 assert(Kind == k_Prefetch && "Invalid access!");
423 return Prefetch.Val;
424 }
425
Oliver Stannarda34e4702015-12-01 10:48:51 +0000426 unsigned getPSBHint() const {
427 assert(Kind == k_PSBHint && "Invalid access!");
428 return PSBHint.Val;
429 }
430
431 StringRef getPSBHintName() const {
432 assert(Kind == k_PSBHint && "Invalid access!");
433 return StringRef(PSBHint.Data, PSBHint.Length);
434 }
435
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000436 StringRef getPrefetchName() const {
437 assert(Kind == k_Prefetch && "Invalid access!");
438 return StringRef(Prefetch.Data, Prefetch.Length);
439 }
440
Tim Northover3b0846e2014-05-24 12:50:23 +0000441 AArch64_AM::ShiftExtendType getShiftExtendType() const {
442 assert(Kind == k_ShiftExtend && "Invalid access!");
443 return ShiftExtend.Type;
444 }
445
446 unsigned getShiftExtendAmount() const {
447 assert(Kind == k_ShiftExtend && "Invalid access!");
448 return ShiftExtend.Amount;
449 }
450
451 bool hasShiftExtendAmount() const {
452 assert(Kind == k_ShiftExtend && "Invalid access!");
453 return ShiftExtend.HasExplicitAmount;
454 }
455
456 bool isImm() const override { return Kind == k_Immediate; }
457 bool isMem() const override { return false; }
458 bool isSImm9() const {
459 if (!isImm())
460 return false;
461 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
462 if (!MCE)
463 return false;
464 int64_t Val = MCE->getValue();
465 return (Val >= -256 && Val < 256);
466 }
467 bool isSImm7s4() const {
468 if (!isImm())
469 return false;
470 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
471 if (!MCE)
472 return false;
473 int64_t Val = MCE->getValue();
474 return (Val >= -256 && Val <= 252 && (Val & 3) == 0);
475 }
476 bool isSImm7s8() const {
477 if (!isImm())
478 return false;
479 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
480 if (!MCE)
481 return false;
482 int64_t Val = MCE->getValue();
483 return (Val >= -512 && Val <= 504 && (Val & 7) == 0);
484 }
485 bool isSImm7s16() const {
486 if (!isImm())
487 return false;
488 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
489 if (!MCE)
490 return false;
491 int64_t Val = MCE->getValue();
492 return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
493 }
494
495 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
496 AArch64MCExpr::VariantKind ELFRefKind;
497 MCSymbolRefExpr::VariantKind DarwinRefKind;
498 int64_t Addend;
499 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
500 Addend)) {
501 // If we don't understand the expression, assume the best and
502 // let the fixup and relocation code deal with it.
503 return true;
504 }
505
506 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
507 ELFRefKind == AArch64MCExpr::VK_LO12 ||
508 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
509 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
510 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
511 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
512 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
513 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
514 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
515 // Note that we don't range-check the addend. It's adjusted modulo page
516 // size when converted, so there is no "out of range" condition when using
517 // @pageoff.
518 return Addend >= 0 && (Addend % Scale) == 0;
519 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
520 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
521 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
522 return Addend == 0;
523 }
524
525 return false;
526 }
527
528 template <int Scale> bool isUImm12Offset() const {
529 if (!isImm())
530 return false;
531
532 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
533 if (!MCE)
534 return isSymbolicUImm12Offset(getImm(), Scale);
535
536 int64_t Val = MCE->getValue();
537 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
538 }
539
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000540 template <int N, int M>
541 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000542 if (!isImm())
543 return false;
544 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
545 if (!MCE)
546 return false;
547 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000548 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000549 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000550
Tim Northover3b0846e2014-05-24 12:50:23 +0000551 bool isLogicalImm32() const {
552 if (!isImm())
553 return false;
554 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
555 if (!MCE)
556 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000557 int64_t Val = MCE->getValue();
558 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
559 return false;
560 Val &= 0xFFFFFFFF;
561 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000562 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000563
Tim Northover3b0846e2014-05-24 12:50:23 +0000564 bool isLogicalImm64() const {
565 if (!isImm())
566 return false;
567 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
568 if (!MCE)
569 return false;
570 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
571 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000572
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000573 bool isLogicalImm32Not() const {
574 if (!isImm())
575 return false;
576 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
577 if (!MCE)
578 return false;
579 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
580 return AArch64_AM::isLogicalImmediate(Val, 32);
581 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000582
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000583 bool isLogicalImm64Not() const {
584 if (!isImm())
585 return false;
586 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
587 if (!MCE)
588 return false;
589 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
590 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000591
Tim Northover3b0846e2014-05-24 12:50:23 +0000592 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000593
Tim Northover3b0846e2014-05-24 12:50:23 +0000594 bool isAddSubImm() const {
595 if (!isShiftedImm() && !isImm())
596 return false;
597
598 const MCExpr *Expr;
599
600 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
601 if (isShiftedImm()) {
602 unsigned Shift = ShiftedImm.ShiftAmount;
603 Expr = ShiftedImm.Val;
604 if (Shift != 0 && Shift != 12)
605 return false;
606 } else {
607 Expr = getImm();
608 }
609
610 AArch64MCExpr::VariantKind ELFRefKind;
611 MCSymbolRefExpr::VariantKind DarwinRefKind;
612 int64_t Addend;
613 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
614 DarwinRefKind, Addend)) {
615 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
616 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
617 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
618 || ELFRefKind == AArch64MCExpr::VK_LO12
619 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
620 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
621 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
622 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
623 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
624 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
625 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
626 }
627
Diana Picusc93518d2016-10-11 09:17:47 +0000628 // If it's a constant, it should be a real immediate in range:
629 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
630 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
631
632 // If it's an expression, we hope for the best and let the fixup/relocation
633 // code deal with it.
634 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000635 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000636
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000637 bool isAddSubImmNeg() const {
638 if (!isShiftedImm() && !isImm())
639 return false;
640
641 const MCExpr *Expr;
642
643 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
644 if (isShiftedImm()) {
645 unsigned Shift = ShiftedImm.ShiftAmount;
646 Expr = ShiftedImm.Val;
647 if (Shift != 0 && Shift != 12)
648 return false;
649 } else
650 Expr = getImm();
651
652 // Otherwise it should be a real negative immediate in range:
653 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
654 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
655 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000656
Tim Northover3b0846e2014-05-24 12:50:23 +0000657 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000658
Tim Northover3b0846e2014-05-24 12:50:23 +0000659 bool isSIMDImmType10() const {
660 if (!isImm())
661 return false;
662 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
663 if (!MCE)
664 return false;
665 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
666 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000667
Tim Northover3b0846e2014-05-24 12:50:23 +0000668 bool isBranchTarget26() const {
669 if (!isImm())
670 return false;
671 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
672 if (!MCE)
673 return true;
674 int64_t Val = MCE->getValue();
675 if (Val & 0x3)
676 return false;
677 return (Val >= -(0x2000000 << 2) && Val <= (0x1ffffff << 2));
678 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000679
Tim Northover3b0846e2014-05-24 12:50:23 +0000680 bool isPCRelLabel19() const {
681 if (!isImm())
682 return false;
683 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
684 if (!MCE)
685 return true;
686 int64_t Val = MCE->getValue();
687 if (Val & 0x3)
688 return false;
689 return (Val >= -(0x40000 << 2) && Val <= (0x3ffff << 2));
690 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000691
Tim Northover3b0846e2014-05-24 12:50:23 +0000692 bool isBranchTarget14() const {
693 if (!isImm())
694 return false;
695 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
696 if (!MCE)
697 return true;
698 int64_t Val = MCE->getValue();
699 if (Val & 0x3)
700 return false;
701 return (Val >= -(0x2000 << 2) && Val <= (0x1fff << 2));
702 }
703
704 bool
705 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
706 if (!isImm())
707 return false;
708
709 AArch64MCExpr::VariantKind ELFRefKind;
710 MCSymbolRefExpr::VariantKind DarwinRefKind;
711 int64_t Addend;
712 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
713 DarwinRefKind, Addend)) {
714 return false;
715 }
716 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
717 return false;
718
719 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
720 if (ELFRefKind == AllowedModifiers[i])
721 return Addend == 0;
722 }
723
724 return false;
725 }
726
727 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000728 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000729 }
730
731 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000732 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
733 AArch64MCExpr::VK_TPREL_G2,
734 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000735 }
736
737 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000738 return isMovWSymbol({
739 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000740 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
741 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000742 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000743 }
744
745 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000746 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
747 AArch64MCExpr::VK_TPREL_G0,
748 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000749 }
750
751 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000752 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000753 }
754
755 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000756 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000757 }
758
759 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000760 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
761 AArch64MCExpr::VK_TPREL_G1_NC,
762 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000763 }
764
765 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000766 return isMovWSymbol(
767 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
768 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000769 }
770
771 template<int RegWidth, int Shift>
772 bool isMOVZMovAlias() const {
773 if (!isImm()) return false;
774
775 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
776 if (!CE) return false;
777 uint64_t Value = CE->getValue();
778
Tim Northoverdaa1c012016-06-16 01:42:25 +0000779 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000780 }
781
782 template<int RegWidth, int Shift>
783 bool isMOVNMovAlias() const {
784 if (!isImm()) return false;
785
786 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
787 if (!CE) return false;
788 uint64_t Value = CE->getValue();
789
Tim Northoverdaa1c012016-06-16 01:42:25 +0000790 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000791 }
792
793 bool isFPImm() const { return Kind == k_FPImm; }
794 bool isBarrier() const { return Kind == k_Barrier; }
795 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000796
Tim Northover3b0846e2014-05-24 12:50:23 +0000797 bool isMRSSystemRegister() const {
798 if (!isSysReg()) return false;
799
Tim Northover7cd58932015-01-22 17:23:04 +0000800 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000801 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000802
Tim Northover3b0846e2014-05-24 12:50:23 +0000803 bool isMSRSystemRegister() const {
804 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000805 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000806 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000807
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000808 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000809 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000810 return (SysReg.PStateField == AArch64PState::PAN ||
811 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000812 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000813
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000814 bool isSystemPStateFieldWithImm0_15() const {
815 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000816 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000817 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000818
Tim Northover3b0846e2014-05-24 12:50:23 +0000819 bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
820 bool isVectorReg() const { return Kind == k_Register && Reg.isVector; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000821
Tim Northover3b0846e2014-05-24 12:50:23 +0000822 bool isVectorRegLo() const {
823 return Kind == k_Register && Reg.isVector &&
824 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
825 Reg.RegNum);
826 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000827
Tim Northover3b0846e2014-05-24 12:50:23 +0000828 bool isGPR32as64() const {
829 return Kind == k_Register && !Reg.isVector &&
830 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
831 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000832
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000833 bool isWSeqPair() const {
834 return Kind == k_Register && !Reg.isVector &&
835 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
836 Reg.RegNum);
837 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000838
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000839 bool isXSeqPair() const {
840 return Kind == k_Register && !Reg.isVector &&
841 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
842 Reg.RegNum);
843 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000844
845 bool isGPR64sp0() const {
846 return Kind == k_Register && !Reg.isVector &&
847 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
848 }
849
850 /// Is this a vector list with the type implicit (presumably attached to the
851 /// instruction itself)?
852 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
853 return Kind == k_VectorList && VectorList.Count == NumRegs &&
854 !VectorList.ElementKind;
855 }
856
857 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
858 bool isTypedVectorList() const {
859 if (Kind != k_VectorList)
860 return false;
861 if (VectorList.Count != NumRegs)
862 return false;
863 if (VectorList.ElementKind != ElementKind)
864 return false;
865 return VectorList.NumElements == NumElements;
866 }
867
868 bool isVectorIndex1() const {
869 return Kind == k_VectorIndex && VectorIndex.Val == 1;
870 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000871
Tim Northover3b0846e2014-05-24 12:50:23 +0000872 bool isVectorIndexB() const {
873 return Kind == k_VectorIndex && VectorIndex.Val < 16;
874 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000875
Tim Northover3b0846e2014-05-24 12:50:23 +0000876 bool isVectorIndexH() const {
877 return Kind == k_VectorIndex && VectorIndex.Val < 8;
878 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000879
Tim Northover3b0846e2014-05-24 12:50:23 +0000880 bool isVectorIndexS() const {
881 return Kind == k_VectorIndex && VectorIndex.Val < 4;
882 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000883
Tim Northover3b0846e2014-05-24 12:50:23 +0000884 bool isVectorIndexD() const {
885 return Kind == k_VectorIndex && VectorIndex.Val < 2;
886 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000887
Tim Northover3b0846e2014-05-24 12:50:23 +0000888 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000889
Tim Northover3b0846e2014-05-24 12:50:23 +0000890 bool isTokenEqual(StringRef Str) const {
891 return Kind == k_Token && getToken() == Str;
892 }
893 bool isSysCR() const { return Kind == k_SysCR; }
894 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000895 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000896 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
897 bool isShifter() const {
898 if (!isShiftExtend())
899 return false;
900
901 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
902 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
903 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
904 ST == AArch64_AM::MSL);
905 }
906 bool isExtend() const {
907 if (!isShiftExtend())
908 return false;
909
910 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
911 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
912 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
913 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
914 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
915 ET == AArch64_AM::LSL) &&
916 getShiftExtendAmount() <= 4;
917 }
918
919 bool isExtend64() const {
920 if (!isExtend())
921 return false;
922 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
923 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
924 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
925 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000926
Tim Northover3b0846e2014-05-24 12:50:23 +0000927 bool isExtendLSL64() const {
928 if (!isExtend())
929 return false;
930 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
931 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
932 ET == AArch64_AM::LSL) &&
933 getShiftExtendAmount() <= 4;
934 }
935
936 template<int Width> bool isMemXExtend() const {
937 if (!isExtend())
938 return false;
939 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
940 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
941 (getShiftExtendAmount() == Log2_32(Width / 8) ||
942 getShiftExtendAmount() == 0);
943 }
944
945 template<int Width> bool isMemWExtend() const {
946 if (!isExtend())
947 return false;
948 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
949 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
950 (getShiftExtendAmount() == Log2_32(Width / 8) ||
951 getShiftExtendAmount() == 0);
952 }
953
954 template <unsigned width>
955 bool isArithmeticShifter() const {
956 if (!isShifter())
957 return false;
958
959 // An arithmetic shifter is LSL, LSR, or ASR.
960 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
961 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
962 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
963 }
964
965 template <unsigned width>
966 bool isLogicalShifter() const {
967 if (!isShifter())
968 return false;
969
970 // A logical shifter is LSL, LSR, ASR or ROR.
971 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
972 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
973 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
974 getShiftExtendAmount() < width;
975 }
976
977 bool isMovImm32Shifter() const {
978 if (!isShifter())
979 return false;
980
981 // A MOVi shifter is LSL of 0, 16, 32, or 48.
982 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
983 if (ST != AArch64_AM::LSL)
984 return false;
985 uint64_t Val = getShiftExtendAmount();
986 return (Val == 0 || Val == 16);
987 }
988
989 bool isMovImm64Shifter() const {
990 if (!isShifter())
991 return false;
992
993 // A MOVi shifter is LSL of 0 or 16.
994 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
995 if (ST != AArch64_AM::LSL)
996 return false;
997 uint64_t Val = getShiftExtendAmount();
998 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
999 }
1000
1001 bool isLogicalVecShifter() const {
1002 if (!isShifter())
1003 return false;
1004
1005 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1006 unsigned Shift = getShiftExtendAmount();
1007 return getShiftExtendType() == AArch64_AM::LSL &&
1008 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1009 }
1010
1011 bool isLogicalVecHalfWordShifter() const {
1012 if (!isLogicalVecShifter())
1013 return false;
1014
1015 // A logical vector shifter is a left shift by 0 or 8.
1016 unsigned Shift = getShiftExtendAmount();
1017 return getShiftExtendType() == AArch64_AM::LSL &&
1018 (Shift == 0 || Shift == 8);
1019 }
1020
1021 bool isMoveVecShifter() const {
1022 if (!isShiftExtend())
1023 return false;
1024
1025 // A logical vector shifter is a left shift by 8 or 16.
1026 unsigned Shift = getShiftExtendAmount();
1027 return getShiftExtendType() == AArch64_AM::MSL &&
1028 (Shift == 8 || Shift == 16);
1029 }
1030
1031 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1032 // to LDUR/STUR when the offset is not legal for the former but is for
1033 // the latter. As such, in addition to checking for being a legal unscaled
1034 // address, also check that it is not a legal scaled address. This avoids
1035 // ambiguity in the matcher.
1036 template<int Width>
1037 bool isSImm9OffsetFB() const {
1038 return isSImm9() && !isUImm12Offset<Width / 8>();
1039 }
1040
1041 bool isAdrpLabel() const {
1042 // Validation was handled during parsing, so we just sanity check that
1043 // something didn't go haywire.
1044 if (!isImm())
1045 return false;
1046
1047 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1048 int64_t Val = CE->getValue();
1049 int64_t Min = - (4096 * (1LL << (21 - 1)));
1050 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1051 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1052 }
1053
1054 return true;
1055 }
1056
1057 bool isAdrLabel() const {
1058 // Validation was handled during parsing, so we just sanity check that
1059 // something didn't go haywire.
1060 if (!isImm())
1061 return false;
1062
1063 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1064 int64_t Val = CE->getValue();
1065 int64_t Min = - (1LL << (21 - 1));
1066 int64_t Max = ((1LL << (21 - 1)) - 1);
1067 return Val >= Min && Val <= Max;
1068 }
1069
1070 return true;
1071 }
1072
1073 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1074 // Add as immediates when possible. Null MCExpr = 0.
1075 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001076 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001077 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001078 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001079 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001080 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001081 }
1082
1083 void addRegOperands(MCInst &Inst, unsigned N) const {
1084 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001085 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001086 }
1087
1088 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1089 assert(N == 1 && "Invalid number of operands!");
1090 assert(
1091 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1092
1093 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1094 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1095 RI->getEncodingValue(getReg()));
1096
Jim Grosbache9119e42015-05-13 18:37:00 +00001097 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001098 }
1099
1100 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1101 assert(N == 1 && "Invalid number of operands!");
1102 assert(
1103 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001104 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001105 }
1106
1107 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
1109 assert(
1110 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001111 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001112 }
1113
1114 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1115 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001116 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001117 }
1118
1119 template <unsigned NumRegs>
1120 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1121 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001122 static const unsigned FirstRegs[] = { AArch64::D0,
1123 AArch64::D0_D1,
1124 AArch64::D0_D1_D2,
1125 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001126 unsigned FirstReg = FirstRegs[NumRegs - 1];
1127
1128 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001129 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001130 }
1131
1132 template <unsigned NumRegs>
1133 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1134 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001135 static const unsigned FirstRegs[] = { AArch64::Q0,
1136 AArch64::Q0_Q1,
1137 AArch64::Q0_Q1_Q2,
1138 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001139 unsigned FirstReg = FirstRegs[NumRegs - 1];
1140
1141 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001142 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001143 }
1144
1145 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1146 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001147 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001148 }
1149
1150 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1151 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001152 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001153 }
1154
1155 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1156 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001157 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001158 }
1159
1160 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001162 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001163 }
1164
1165 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001167 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001168 }
1169
1170 void addImmOperands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 // If this is a pageoff symrefexpr with an addend, adjust the addend
1173 // to be only the page-offset portion. Otherwise, just add the expr
1174 // as-is.
1175 addExpr(Inst, getImm());
1176 }
1177
1178 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1179 assert(N == 2 && "Invalid number of operands!");
1180 if (isShiftedImm()) {
1181 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001182 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001183 } else {
1184 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001185 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001186 }
1187 }
1188
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001189 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 2 && "Invalid number of operands!");
1191
1192 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1193 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1194 int64_t Val = -CE->getValue();
1195 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1196
1197 Inst.addOperand(MCOperand::createImm(Val));
1198 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1199 }
1200
Tim Northover3b0846e2014-05-24 12:50:23 +00001201 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001203 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001204 }
1205
1206 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1207 assert(N == 1 && "Invalid number of operands!");
1208 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1209 if (!MCE)
1210 addExpr(Inst, getImm());
1211 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001212 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001213 }
1214
1215 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1216 addImmOperands(Inst, N);
1217 }
1218
1219 template<int Scale>
1220 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1221 assert(N == 1 && "Invalid number of operands!");
1222 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1223
1224 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001225 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001226 return;
1227 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001228 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001229 }
1230
1231 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001233 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001234 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001235 }
1236
1237 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1238 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001239 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001240 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001241 }
1242
1243 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1244 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001245 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001246 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001247 }
1248
1249 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001251 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001252 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001253 }
1254
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001255 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
1257 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1258 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1259 }
1260
Tim Northover3b0846e2014-05-24 12:50:23 +00001261 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001263 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001264 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001265 }
1266
1267 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1268 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001269 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001270 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001271 }
1272
1273 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1274 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001275 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001276 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001277 }
1278
1279 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1280 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001281 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001282 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001283 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001284 }
1285
1286 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1287 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001288 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001289 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001290 }
1291
1292 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1293 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001294 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001295 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001296 }
1297
1298 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1299 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001300 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001301 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001302 }
1303
1304 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1305 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001306 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001307 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001308 }
1309
1310 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1311 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001312 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001313 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001314 }
1315
1316 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1317 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001318 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001319 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001320 }
1321
1322 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1323 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001324 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001325 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001326 }
1327
1328 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001330 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001331 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001332 }
1333
1334 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1335 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001336 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001337 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
1340 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001342 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001343 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001344 }
1345
1346 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1347 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001348 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001349 uint64_t encoding =
1350 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001351 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001352 }
1353
1354 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1355 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001356 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001357 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001358 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001359 }
1360
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001361 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1362 assert(N == 1 && "Invalid number of operands!");
1363 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1364 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1365 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001366 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001367 }
1368
1369 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1370 assert(N == 1 && "Invalid number of operands!");
1371 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1372 uint64_t encoding =
1373 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001374 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001375 }
1376
Tim Northover3b0846e2014-05-24 12:50:23 +00001377 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001379 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001380 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001381 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001382 }
1383
1384 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1385 // Branch operands don't encode the low bits, so shift them off
1386 // here. If it's a label, however, just put it on directly as there's
1387 // not enough information now to do anything.
1388 assert(N == 1 && "Invalid number of operands!");
1389 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1390 if (!MCE) {
1391 addExpr(Inst, getImm());
1392 return;
1393 }
1394 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001395 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001396 }
1397
1398 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1399 // Branch operands don't encode the low bits, so shift them off
1400 // here. If it's a label, however, just put it on directly as there's
1401 // not enough information now to do anything.
1402 assert(N == 1 && "Invalid number of operands!");
1403 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1404 if (!MCE) {
1405 addExpr(Inst, getImm());
1406 return;
1407 }
1408 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001409 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001410 }
1411
1412 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1413 // Branch operands don't encode the low bits, so shift them off
1414 // here. If it's a label, however, just put it on directly as there's
1415 // not enough information now to do anything.
1416 assert(N == 1 && "Invalid number of operands!");
1417 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1418 if (!MCE) {
1419 addExpr(Inst, getImm());
1420 return;
1421 }
1422 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001423 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001424 }
1425
1426 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1427 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 }
1430
1431 void addBarrierOperands(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(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438
Jim Grosbache9119e42015-05-13 18:37:00 +00001439 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001440 }
1441
1442 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1443 assert(N == 1 && "Invalid number of operands!");
1444
Jim Grosbache9119e42015-05-13 18:37:00 +00001445 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001446 }
1447
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001448 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1449 assert(N == 1 && "Invalid number of operands!");
1450
1451 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1452 }
1453
1454 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001455 assert(N == 1 && "Invalid number of operands!");
1456
Jim Grosbache9119e42015-05-13 18:37:00 +00001457 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 }
1459
1460 void addSysCROperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001462 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001463 }
1464
1465 void addPrefetchOperands(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(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001468 }
1469
Oliver Stannarda34e4702015-12-01 10:48:51 +00001470 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
1472 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1473 }
1474
Tim Northover3b0846e2014-05-24 12:50:23 +00001475 void addShifterOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 unsigned Imm =
1478 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001479 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 }
1481
1482 void addExtendOperands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
1484 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1485 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1486 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001487 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001488 }
1489
1490 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1491 assert(N == 1 && "Invalid number of operands!");
1492 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1493 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1494 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001495 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001496 }
1497
1498 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1499 assert(N == 2 && "Invalid number of operands!");
1500 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1501 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001502 Inst.addOperand(MCOperand::createImm(IsSigned));
1503 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
1506 // For 8-bit load/store instructions with a register offset, both the
1507 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1508 // they're disambiguated by whether the shift was explicit or implicit rather
1509 // than its size.
1510 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1511 assert(N == 2 && "Invalid number of operands!");
1512 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1513 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001514 Inst.addOperand(MCOperand::createImm(IsSigned));
1515 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 }
1517
1518 template<int Shift>
1519 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1520 assert(N == 1 && "Invalid number of operands!");
1521
1522 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1523 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001524 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001525 }
1526
1527 template<int Shift>
1528 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1529 assert(N == 1 && "Invalid number of operands!");
1530
1531 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1532 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001533 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001534 }
1535
1536 void print(raw_ostream &OS) const override;
1537
David Blaikie960ea3f2014-06-08 16:18:35 +00001538 static std::unique_ptr<AArch64Operand>
1539 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1540 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001541 Op->Tok.Data = Str.data();
1542 Op->Tok.Length = Str.size();
1543 Op->Tok.IsSuffix = IsSuffix;
1544 Op->StartLoc = S;
1545 Op->EndLoc = S;
1546 return Op;
1547 }
1548
David Blaikie960ea3f2014-06-08 16:18:35 +00001549 static std::unique_ptr<AArch64Operand>
1550 CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
1551 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001552 Op->Reg.RegNum = RegNum;
1553 Op->Reg.isVector = isVector;
1554 Op->StartLoc = S;
1555 Op->EndLoc = E;
1556 return Op;
1557 }
1558
David Blaikie960ea3f2014-06-08 16:18:35 +00001559 static std::unique_ptr<AArch64Operand>
1560 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1561 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1562 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001563 Op->VectorList.RegNum = RegNum;
1564 Op->VectorList.Count = Count;
1565 Op->VectorList.NumElements = NumElements;
1566 Op->VectorList.ElementKind = ElementKind;
1567 Op->StartLoc = S;
1568 Op->EndLoc = E;
1569 return Op;
1570 }
1571
David Blaikie960ea3f2014-06-08 16:18:35 +00001572 static std::unique_ptr<AArch64Operand>
1573 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1574 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001575 Op->VectorIndex.Val = Idx;
1576 Op->StartLoc = S;
1577 Op->EndLoc = E;
1578 return Op;
1579 }
1580
David Blaikie960ea3f2014-06-08 16:18:35 +00001581 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1582 SMLoc E, MCContext &Ctx) {
1583 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001584 Op->Imm.Val = Val;
1585 Op->StartLoc = S;
1586 Op->EndLoc = E;
1587 return Op;
1588 }
1589
David Blaikie960ea3f2014-06-08 16:18:35 +00001590 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1591 unsigned ShiftAmount,
1592 SMLoc S, SMLoc E,
1593 MCContext &Ctx) {
1594 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001595 Op->ShiftedImm .Val = Val;
1596 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1597 Op->StartLoc = S;
1598 Op->EndLoc = E;
1599 return Op;
1600 }
1601
David Blaikie960ea3f2014-06-08 16:18:35 +00001602 static std::unique_ptr<AArch64Operand>
1603 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1604 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001605 Op->CondCode.Code = Code;
1606 Op->StartLoc = S;
1607 Op->EndLoc = E;
1608 return Op;
1609 }
1610
David Blaikie960ea3f2014-06-08 16:18:35 +00001611 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1612 MCContext &Ctx) {
1613 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001614 Op->FPImm.Val = Val;
1615 Op->StartLoc = S;
1616 Op->EndLoc = S;
1617 return Op;
1618 }
1619
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001620 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1621 StringRef Str,
1622 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001623 MCContext &Ctx) {
1624 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001625 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001626 Op->Barrier.Data = Str.data();
1627 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001628 Op->StartLoc = S;
1629 Op->EndLoc = S;
1630 return Op;
1631 }
1632
Tim Northover7cd58932015-01-22 17:23:04 +00001633 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1634 uint32_t MRSReg,
1635 uint32_t MSRReg,
1636 uint32_t PStateField,
1637 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001638 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 Op->SysReg.Data = Str.data();
1640 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001641 Op->SysReg.MRSReg = MRSReg;
1642 Op->SysReg.MSRReg = MSRReg;
1643 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001644 Op->StartLoc = S;
1645 Op->EndLoc = S;
1646 return Op;
1647 }
1648
David Blaikie960ea3f2014-06-08 16:18:35 +00001649 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1650 SMLoc E, MCContext &Ctx) {
1651 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001652 Op->SysCRImm.Val = Val;
1653 Op->StartLoc = S;
1654 Op->EndLoc = E;
1655 return Op;
1656 }
1657
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001658 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1659 StringRef Str,
1660 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001661 MCContext &Ctx) {
1662 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001663 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001664 Op->Barrier.Data = Str.data();
1665 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001666 Op->StartLoc = S;
1667 Op->EndLoc = S;
1668 return Op;
1669 }
1670
Oliver Stannarda34e4702015-12-01 10:48:51 +00001671 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1672 StringRef Str,
1673 SMLoc S,
1674 MCContext &Ctx) {
1675 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1676 Op->PSBHint.Val = Val;
1677 Op->PSBHint.Data = Str.data();
1678 Op->PSBHint.Length = Str.size();
1679 Op->StartLoc = S;
1680 Op->EndLoc = S;
1681 return Op;
1682 }
1683
David Blaikie960ea3f2014-06-08 16:18:35 +00001684 static std::unique_ptr<AArch64Operand>
1685 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1686 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1687 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001688 Op->ShiftExtend.Type = ShOp;
1689 Op->ShiftExtend.Amount = Val;
1690 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1691 Op->StartLoc = S;
1692 Op->EndLoc = E;
1693 return Op;
1694 }
1695};
1696
1697} // end anonymous namespace.
1698
1699void AArch64Operand::print(raw_ostream &OS) const {
1700 switch (Kind) {
1701 case k_FPImm:
1702 OS << "<fpimm " << getFPImm() << "("
1703 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1704 break;
1705 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001706 StringRef Name = getBarrierName();
1707 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001708 OS << "<barrier " << Name << ">";
1709 else
1710 OS << "<barrier invalid #" << getBarrier() << ">";
1711 break;
1712 }
1713 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001714 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001715 break;
1716 case k_ShiftedImm: {
1717 unsigned Shift = getShiftedImmShift();
1718 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001719 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001720 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1721 break;
1722 }
1723 case k_CondCode:
1724 OS << "<condcode " << getCondCode() << ">";
1725 break;
1726 case k_Register:
1727 OS << "<register " << getReg() << ">";
1728 break;
1729 case k_VectorList: {
1730 OS << "<vectorlist ";
1731 unsigned Reg = getVectorListStart();
1732 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1733 OS << Reg + i << " ";
1734 OS << ">";
1735 break;
1736 }
1737 case k_VectorIndex:
1738 OS << "<vectorindex " << getVectorIndex() << ">";
1739 break;
1740 case k_SysReg:
1741 OS << "<sysreg: " << getSysReg() << '>';
1742 break;
1743 case k_Token:
1744 OS << "'" << getToken() << "'";
1745 break;
1746 case k_SysCR:
1747 OS << "c" << getSysCR();
1748 break;
1749 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001750 StringRef Name = getPrefetchName();
1751 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001752 OS << "<prfop " << Name << ">";
1753 else
1754 OS << "<prfop invalid #" << getPrefetch() << ">";
1755 break;
1756 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001757 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001758 OS << getPSBHintName();
1759 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001760 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001761 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1762 << getShiftExtendAmount();
1763 if (!hasShiftExtendAmount())
1764 OS << "<imp>";
1765 OS << '>';
1766 break;
1767 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001768}
1769
1770/// @name Auto-generated Match Functions
1771/// {
1772
1773static unsigned MatchRegisterName(StringRef Name);
1774
1775/// }
1776
1777static unsigned matchVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001778 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001779 .Case("v0", AArch64::Q0)
1780 .Case("v1", AArch64::Q1)
1781 .Case("v2", AArch64::Q2)
1782 .Case("v3", AArch64::Q3)
1783 .Case("v4", AArch64::Q4)
1784 .Case("v5", AArch64::Q5)
1785 .Case("v6", AArch64::Q6)
1786 .Case("v7", AArch64::Q7)
1787 .Case("v8", AArch64::Q8)
1788 .Case("v9", AArch64::Q9)
1789 .Case("v10", AArch64::Q10)
1790 .Case("v11", AArch64::Q11)
1791 .Case("v12", AArch64::Q12)
1792 .Case("v13", AArch64::Q13)
1793 .Case("v14", AArch64::Q14)
1794 .Case("v15", AArch64::Q15)
1795 .Case("v16", AArch64::Q16)
1796 .Case("v17", AArch64::Q17)
1797 .Case("v18", AArch64::Q18)
1798 .Case("v19", AArch64::Q19)
1799 .Case("v20", AArch64::Q20)
1800 .Case("v21", AArch64::Q21)
1801 .Case("v22", AArch64::Q22)
1802 .Case("v23", AArch64::Q23)
1803 .Case("v24", AArch64::Q24)
1804 .Case("v25", AArch64::Q25)
1805 .Case("v26", AArch64::Q26)
1806 .Case("v27", AArch64::Q27)
1807 .Case("v28", AArch64::Q28)
1808 .Case("v29", AArch64::Q29)
1809 .Case("v30", AArch64::Q30)
1810 .Case("v31", AArch64::Q31)
1811 .Default(0);
1812}
1813
1814static bool isValidVectorKind(StringRef Name) {
1815 return StringSwitch<bool>(Name.lower())
1816 .Case(".8b", true)
1817 .Case(".16b", true)
1818 .Case(".4h", true)
1819 .Case(".8h", true)
1820 .Case(".2s", true)
1821 .Case(".4s", true)
1822 .Case(".1d", true)
1823 .Case(".2d", true)
1824 .Case(".1q", true)
1825 // Accept the width neutral ones, too, for verbose syntax. If those
1826 // aren't used in the right places, the token operand won't match so
1827 // all will work out.
1828 .Case(".b", true)
1829 .Case(".h", true)
1830 .Case(".s", true)
1831 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001832 // Needed for fp16 scalar pairwise reductions
1833 .Case(".2h", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001834 .Default(false);
1835}
1836
1837static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1838 char &ElementKind) {
1839 assert(isValidVectorKind(Name));
1840
1841 ElementKind = Name.lower()[Name.size() - 1];
1842 NumElements = 0;
1843
1844 if (Name.size() == 2)
1845 return;
1846
1847 // Parse the lane count
1848 Name = Name.drop_front();
1849 while (isdigit(Name.front())) {
1850 NumElements = 10 * NumElements + (Name.front() - '0');
1851 Name = Name.drop_front();
1852 }
1853}
1854
1855bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1856 SMLoc &EndLoc) {
1857 StartLoc = getLoc();
1858 RegNo = tryParseRegister();
1859 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1860 return (RegNo == (unsigned)-1);
1861}
1862
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001863// Matches a register name or register alias previously defined by '.req'
1864unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
1865 bool isVector) {
1866 unsigned RegNum = isVector ? matchVectorRegName(Name)
1867 : MatchRegisterName(Name);
1868
1869 if (RegNum == 0) {
1870 // Check for aliases registered via .req. Canonicalize to lower case.
1871 // That's more consistent since register names are case insensitive, and
1872 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1873 auto Entry = RegisterReqs.find(Name.lower());
1874 if (Entry == RegisterReqs.end())
1875 return 0;
1876 // set RegNum if the match is the right kind of register
1877 if (isVector == Entry->getValue().first)
1878 RegNum = Entry->getValue().second;
1879 }
1880 return RegNum;
1881}
1882
Tim Northover3b0846e2014-05-24 12:50:23 +00001883/// tryParseRegister - Try to parse a register name. The token must be an
1884/// Identifier when called, and if it is a register name the token is eaten and
1885/// the register is added to the operand list.
1886int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001887 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001888 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001889 if (Tok.isNot(AsmToken::Identifier))
1890 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00001891
1892 std::string lowerCase = Tok.getString().lower();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001893 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
Tim Northover3b0846e2014-05-24 12:50:23 +00001894 // Also handle a few aliases of registers.
1895 if (RegNum == 0)
1896 RegNum = StringSwitch<unsigned>(lowerCase)
1897 .Case("fp", AArch64::FP)
1898 .Case("lr", AArch64::LR)
1899 .Case("x31", AArch64::XZR)
1900 .Case("w31", AArch64::WZR)
1901 .Default(0);
1902
1903 if (RegNum == 0)
1904 return -1;
1905
1906 Parser.Lex(); // Eat identifier token.
1907 return RegNum;
1908}
1909
1910/// tryMatchVectorRegister - Try to parse a vector register name with optional
1911/// kind specifier. If it is a register specifier, eat the token and return it.
1912int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001913 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001914 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1915 TokError("vector register expected");
1916 return -1;
1917 }
1918
1919 StringRef Name = Parser.getTok().getString();
1920 // If there is a kind specifier, it's separated from the register name by
1921 // a '.'.
1922 size_t Start = 0, Next = Name.find('.');
1923 StringRef Head = Name.slice(Start, Next);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001924 unsigned RegNum = matchRegisterNameAlias(Head, true);
1925
Tim Northover3b0846e2014-05-24 12:50:23 +00001926 if (RegNum) {
1927 if (Next != StringRef::npos) {
1928 Kind = Name.slice(Next, StringRef::npos);
1929 if (!isValidVectorKind(Kind)) {
1930 TokError("invalid vector kind qualifier");
1931 return -1;
1932 }
1933 }
1934 Parser.Lex(); // Eat the register token.
1935 return RegNum;
1936 }
1937
1938 if (expected)
1939 TokError("vector register expected");
1940 return -1;
1941}
1942
1943/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00001944OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001945AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001946 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001947 SMLoc S = getLoc();
1948
1949 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1950 Error(S, "Expected cN operand where 0 <= N <= 15");
1951 return MatchOperand_ParseFail;
1952 }
1953
1954 StringRef Tok = Parser.getTok().getIdentifier();
1955 if (Tok[0] != 'c' && Tok[0] != 'C') {
1956 Error(S, "Expected cN operand where 0 <= N <= 15");
1957 return MatchOperand_ParseFail;
1958 }
1959
1960 uint32_t CRNum;
1961 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
1962 if (BadNum || CRNum > 15) {
1963 Error(S, "Expected cN operand where 0 <= N <= 15");
1964 return MatchOperand_ParseFail;
1965 }
1966
1967 Parser.Lex(); // Eat identifier token.
1968 Operands.push_back(
1969 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
1970 return MatchOperand_Success;
1971}
1972
1973/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00001974OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001975AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001976 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001977 SMLoc S = getLoc();
1978 const AsmToken &Tok = Parser.getTok();
1979 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00001980 // Eat optional hash.
1981 if (parseOptionalToken(AsmToken::Hash) ||
1982 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001983 const MCExpr *ImmVal;
1984 if (getParser().parseExpression(ImmVal))
1985 return MatchOperand_ParseFail;
1986
1987 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1988 if (!MCE) {
1989 TokError("immediate value expected for prefetch operand");
1990 return MatchOperand_ParseFail;
1991 }
1992 unsigned prfop = MCE->getValue();
1993 if (prfop > 31) {
1994 TokError("prefetch operand out of range, [0,31] expected");
1995 return MatchOperand_ParseFail;
1996 }
1997
Tim Northovere6ae6762016-07-05 21:23:04 +00001998 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
1999 Operands.push_back(AArch64Operand::CreatePrefetch(
2000 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002001 return MatchOperand_Success;
2002 }
2003
2004 if (Tok.isNot(AsmToken::Identifier)) {
2005 TokError("pre-fetch hint expected");
2006 return MatchOperand_ParseFail;
2007 }
2008
Tim Northovere6ae6762016-07-05 21:23:04 +00002009 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2010 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002011 TokError("pre-fetch hint expected");
2012 return MatchOperand_ParseFail;
2013 }
2014
2015 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002016 Operands.push_back(AArch64Operand::CreatePrefetch(
2017 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002018 return MatchOperand_Success;
2019}
2020
Oliver Stannarda34e4702015-12-01 10:48:51 +00002021/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002022OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002023AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2024 MCAsmParser &Parser = getParser();
2025 SMLoc S = getLoc();
2026 const AsmToken &Tok = Parser.getTok();
2027 if (Tok.isNot(AsmToken::Identifier)) {
2028 TokError("invalid operand for instruction");
2029 return MatchOperand_ParseFail;
2030 }
2031
Tim Northovere6ae6762016-07-05 21:23:04 +00002032 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2033 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002034 TokError("invalid operand for instruction");
2035 return MatchOperand_ParseFail;
2036 }
2037
2038 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002039 Operands.push_back(AArch64Operand::CreatePSBHint(
2040 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002041 return MatchOperand_Success;
2042}
2043
Tim Northover3b0846e2014-05-24 12:50:23 +00002044/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2045/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002046OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002047AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002048 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002049 SMLoc S = getLoc();
2050 const MCExpr *Expr;
2051
2052 if (Parser.getTok().is(AsmToken::Hash)) {
2053 Parser.Lex(); // Eat hash token.
2054 }
2055
2056 if (parseSymbolicImmVal(Expr))
2057 return MatchOperand_ParseFail;
2058
2059 AArch64MCExpr::VariantKind ELFRefKind;
2060 MCSymbolRefExpr::VariantKind DarwinRefKind;
2061 int64_t Addend;
2062 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2063 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2064 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2065 // No modifier was specified at all; this is the syntax for an ELF basic
2066 // ADRP relocation (unfortunately).
2067 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002068 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002069 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2070 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2071 Addend != 0) {
2072 Error(S, "gotpage label reference not allowed an addend");
2073 return MatchOperand_ParseFail;
2074 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2075 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2076 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2077 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2078 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2079 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2080 // The operand must be an @page or @gotpage qualified symbolref.
2081 Error(S, "page or gotpage label reference expected");
2082 return MatchOperand_ParseFail;
2083 }
2084 }
2085
2086 // We have either a label reference possibly with addend or an immediate. The
2087 // addend is a raw value here. The linker will adjust it to only reference the
2088 // page.
2089 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2090 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2091
2092 return MatchOperand_Success;
2093}
2094
2095/// tryParseAdrLabel - Parse and validate a source label for the ADR
2096/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002097OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002098AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2099 SMLoc S = getLoc();
2100 const MCExpr *Expr;
2101
Nirav Davee833c6c2016-11-08 18:31:04 +00002102 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002103 if (getParser().parseExpression(Expr))
2104 return MatchOperand_ParseFail;
2105
2106 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2107 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2108
2109 return MatchOperand_Success;
2110}
2111
2112/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002113OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002114AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002115 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002116 SMLoc S = getLoc();
2117
Nirav Davee833c6c2016-11-08 18:31:04 +00002118 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002119
2120 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002121 bool isNegative = parseOptionalToken(AsmToken::Minus);
2122
Tim Northover3b0846e2014-05-24 12:50:23 +00002123 const AsmToken &Tok = Parser.getTok();
2124 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002125 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002126 if (isNegative)
2127 RealVal.changeSign();
2128
Tim Northover3b0846e2014-05-24 12:50:23 +00002129 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002130 int Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2131 Parser.Lex(); // Eat the token.
2132 // Check for out of range values. As an exception, we let Zero through,
2133 // as we handle that special case in post-processing before matching in
2134 // order to use the zero register for it.
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002135 if (Val == -1 && !RealVal.isPosZero()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002136 TokError("expected compatible register or floating-point constant");
2137 return MatchOperand_ParseFail;
2138 }
2139 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2140 return MatchOperand_Success;
2141 }
2142 if (Tok.is(AsmToken::Integer)) {
2143 int64_t Val;
2144 if (!isNegative && Tok.getString().startswith("0x")) {
2145 Val = Tok.getIntVal();
2146 if (Val > 255 || Val < 0) {
2147 TokError("encoded floating point value out of range");
2148 return MatchOperand_ParseFail;
2149 }
2150 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002151 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002152 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2153 // If we had a '-' in front, toggle the sign bit.
2154 IntVal ^= (uint64_t)isNegative << 63;
2155 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2156 }
2157 Parser.Lex(); // Eat the token.
2158 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2159 return MatchOperand_Success;
2160 }
2161
2162 if (!Hash)
2163 return MatchOperand_NoMatch;
2164
2165 TokError("invalid floating point immediate");
2166 return MatchOperand_ParseFail;
2167}
2168
2169/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002170OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002171AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002172 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002173 SMLoc S = getLoc();
2174
2175 if (Parser.getTok().is(AsmToken::Hash))
2176 Parser.Lex(); // Eat '#'
2177 else if (Parser.getTok().isNot(AsmToken::Integer))
2178 // Operand should start from # or should be integer, emit error otherwise.
2179 return MatchOperand_NoMatch;
2180
2181 const MCExpr *Imm;
2182 if (parseSymbolicImmVal(Imm))
2183 return MatchOperand_ParseFail;
2184 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2185 uint64_t ShiftAmount = 0;
2186 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2187 if (MCE) {
2188 int64_t Val = MCE->getValue();
2189 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002190 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002191 ShiftAmount = 12;
2192 }
2193 }
2194 SMLoc E = Parser.getTok().getLoc();
2195 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2196 getContext()));
2197 return MatchOperand_Success;
2198 }
2199
2200 // Eat ','
2201 Parser.Lex();
2202
2203 // The optional operand must be "lsl #N" where N is non-negative.
2204 if (!Parser.getTok().is(AsmToken::Identifier) ||
2205 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2206 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2207 return MatchOperand_ParseFail;
2208 }
2209
2210 // Eat 'lsl'
2211 Parser.Lex();
2212
Nirav Davee833c6c2016-11-08 18:31:04 +00002213 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002214
2215 if (Parser.getTok().isNot(AsmToken::Integer)) {
2216 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2217 return MatchOperand_ParseFail;
2218 }
2219
2220 int64_t ShiftAmount = Parser.getTok().getIntVal();
2221
2222 if (ShiftAmount < 0) {
2223 Error(Parser.getTok().getLoc(), "positive shift amount required");
2224 return MatchOperand_ParseFail;
2225 }
2226 Parser.Lex(); // Eat the number
2227
2228 SMLoc E = Parser.getTok().getLoc();
2229 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2230 S, E, getContext()));
2231 return MatchOperand_Success;
2232}
2233
2234/// parseCondCodeString - Parse a Condition Code string.
2235AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2236 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2237 .Case("eq", AArch64CC::EQ)
2238 .Case("ne", AArch64CC::NE)
2239 .Case("cs", AArch64CC::HS)
2240 .Case("hs", AArch64CC::HS)
2241 .Case("cc", AArch64CC::LO)
2242 .Case("lo", AArch64CC::LO)
2243 .Case("mi", AArch64CC::MI)
2244 .Case("pl", AArch64CC::PL)
2245 .Case("vs", AArch64CC::VS)
2246 .Case("vc", AArch64CC::VC)
2247 .Case("hi", AArch64CC::HI)
2248 .Case("ls", AArch64CC::LS)
2249 .Case("ge", AArch64CC::GE)
2250 .Case("lt", AArch64CC::LT)
2251 .Case("gt", AArch64CC::GT)
2252 .Case("le", AArch64CC::LE)
2253 .Case("al", AArch64CC::AL)
2254 .Case("nv", AArch64CC::NV)
2255 .Default(AArch64CC::Invalid);
2256 return CC;
2257}
2258
2259/// parseCondCode - Parse a Condition Code operand.
2260bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2261 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002262 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002263 SMLoc S = getLoc();
2264 const AsmToken &Tok = Parser.getTok();
2265 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2266
2267 StringRef Cond = Tok.getString();
2268 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2269 if (CC == AArch64CC::Invalid)
2270 return TokError("invalid condition code");
2271 Parser.Lex(); // Eat identifier token.
2272
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002273 if (invertCondCode) {
2274 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2275 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002276 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002277 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002278
2279 Operands.push_back(
2280 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2281 return false;
2282}
2283
2284/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2285/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002286OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002287AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002288 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002289 const AsmToken &Tok = Parser.getTok();
2290 std::string LowerID = Tok.getString().lower();
2291 AArch64_AM::ShiftExtendType ShOp =
2292 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2293 .Case("lsl", AArch64_AM::LSL)
2294 .Case("lsr", AArch64_AM::LSR)
2295 .Case("asr", AArch64_AM::ASR)
2296 .Case("ror", AArch64_AM::ROR)
2297 .Case("msl", AArch64_AM::MSL)
2298 .Case("uxtb", AArch64_AM::UXTB)
2299 .Case("uxth", AArch64_AM::UXTH)
2300 .Case("uxtw", AArch64_AM::UXTW)
2301 .Case("uxtx", AArch64_AM::UXTX)
2302 .Case("sxtb", AArch64_AM::SXTB)
2303 .Case("sxth", AArch64_AM::SXTH)
2304 .Case("sxtw", AArch64_AM::SXTW)
2305 .Case("sxtx", AArch64_AM::SXTX)
2306 .Default(AArch64_AM::InvalidShiftExtend);
2307
2308 if (ShOp == AArch64_AM::InvalidShiftExtend)
2309 return MatchOperand_NoMatch;
2310
2311 SMLoc S = Tok.getLoc();
2312 Parser.Lex();
2313
Nirav Davee833c6c2016-11-08 18:31:04 +00002314 bool Hash = parseOptionalToken(AsmToken::Hash);
2315
Tim Northover3b0846e2014-05-24 12:50:23 +00002316 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2317 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2318 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2319 ShOp == AArch64_AM::MSL) {
2320 // We expect a number here.
2321 TokError("expected #imm after shift specifier");
2322 return MatchOperand_ParseFail;
2323 }
2324
Chad Rosier2ff37b82016-12-27 16:58:09 +00002325 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002326 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2327 Operands.push_back(
2328 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2329 return MatchOperand_Success;
2330 }
2331
Chad Rosier2ff37b82016-12-27 16:58:09 +00002332 // Make sure we do actually have a number, identifier or a parenthesized
2333 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002334 SMLoc E = Parser.getTok().getLoc();
2335 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002336 !Parser.getTok().is(AsmToken::LParen) &&
2337 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002338 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002339 return MatchOperand_ParseFail;
2340 }
2341
2342 const MCExpr *ImmVal;
2343 if (getParser().parseExpression(ImmVal))
2344 return MatchOperand_ParseFail;
2345
2346 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2347 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002348 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002349 return MatchOperand_ParseFail;
2350 }
2351
Jim Grosbach57fd2622014-09-23 22:16:02 +00002352 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002353 Operands.push_back(AArch64Operand::CreateShiftExtend(
2354 ShOp, MCE->getValue(), true, S, E, getContext()));
2355 return MatchOperand_Success;
2356}
2357
2358/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2359/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2360bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2361 OperandVector &Operands) {
2362 if (Name.find('.') != StringRef::npos)
2363 return TokError("invalid operand");
2364
2365 Mnemonic = Name;
2366 Operands.push_back(
2367 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2368
Rafael Espindola961d4692014-11-11 05:18:41 +00002369 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002370 const AsmToken &Tok = Parser.getTok();
2371 StringRef Op = Tok.getString();
2372 SMLoc S = Tok.getLoc();
2373
2374 const MCExpr *Expr = nullptr;
2375
2376#define SYS_ALIAS(op1, Cn, Cm, op2) \
2377 do { \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002378 Expr = MCConstantExpr::create(op1, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002379 Operands.push_back( \
2380 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2381 Operands.push_back( \
2382 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext())); \
2383 Operands.push_back( \
2384 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext())); \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002385 Expr = MCConstantExpr::create(op2, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002386 Operands.push_back( \
2387 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
Eugene Zelenko049b0172017-01-06 00:30:53 +00002388 } while (false)
Tim Northover3b0846e2014-05-24 12:50:23 +00002389
2390 if (Mnemonic == "ic") {
2391 if (!Op.compare_lower("ialluis")) {
2392 // SYS #0, C7, C1, #0
2393 SYS_ALIAS(0, 7, 1, 0);
2394 } else if (!Op.compare_lower("iallu")) {
2395 // SYS #0, C7, C5, #0
2396 SYS_ALIAS(0, 7, 5, 0);
2397 } else if (!Op.compare_lower("ivau")) {
2398 // SYS #3, C7, C5, #1
2399 SYS_ALIAS(3, 7, 5, 1);
2400 } else {
2401 return TokError("invalid operand for IC instruction");
2402 }
2403 } else if (Mnemonic == "dc") {
2404 if (!Op.compare_lower("zva")) {
2405 // SYS #3, C7, C4, #1
2406 SYS_ALIAS(3, 7, 4, 1);
2407 } else if (!Op.compare_lower("ivac")) {
2408 // SYS #3, C7, C6, #1
2409 SYS_ALIAS(0, 7, 6, 1);
2410 } else if (!Op.compare_lower("isw")) {
2411 // SYS #0, C7, C6, #2
2412 SYS_ALIAS(0, 7, 6, 2);
2413 } else if (!Op.compare_lower("cvac")) {
2414 // SYS #3, C7, C10, #1
2415 SYS_ALIAS(3, 7, 10, 1);
2416 } else if (!Op.compare_lower("csw")) {
2417 // SYS #0, C7, C10, #2
2418 SYS_ALIAS(0, 7, 10, 2);
2419 } else if (!Op.compare_lower("cvau")) {
2420 // SYS #3, C7, C11, #1
2421 SYS_ALIAS(3, 7, 11, 1);
2422 } else if (!Op.compare_lower("civac")) {
2423 // SYS #3, C7, C14, #1
2424 SYS_ALIAS(3, 7, 14, 1);
2425 } else if (!Op.compare_lower("cisw")) {
2426 // SYS #0, C7, C14, #2
2427 SYS_ALIAS(0, 7, 14, 2);
Oliver Stannard1a81cc9f2015-11-26 15:28:47 +00002428 } else if (!Op.compare_lower("cvap")) {
2429 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2430 // SYS #3, C7, C12, #1
2431 SYS_ALIAS(3, 7, 12, 1);
2432 } else {
2433 return TokError("DC CVAP requires ARMv8.2a");
2434 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002435 } else {
2436 return TokError("invalid operand for DC instruction");
2437 }
2438 } else if (Mnemonic == "at") {
2439 if (!Op.compare_lower("s1e1r")) {
2440 // SYS #0, C7, C8, #0
2441 SYS_ALIAS(0, 7, 8, 0);
2442 } else if (!Op.compare_lower("s1e2r")) {
2443 // SYS #4, C7, C8, #0
2444 SYS_ALIAS(4, 7, 8, 0);
2445 } else if (!Op.compare_lower("s1e3r")) {
2446 // SYS #6, C7, C8, #0
2447 SYS_ALIAS(6, 7, 8, 0);
2448 } else if (!Op.compare_lower("s1e1w")) {
2449 // SYS #0, C7, C8, #1
2450 SYS_ALIAS(0, 7, 8, 1);
2451 } else if (!Op.compare_lower("s1e2w")) {
2452 // SYS #4, C7, C8, #1
2453 SYS_ALIAS(4, 7, 8, 1);
2454 } else if (!Op.compare_lower("s1e3w")) {
2455 // SYS #6, C7, C8, #1
2456 SYS_ALIAS(6, 7, 8, 1);
2457 } else if (!Op.compare_lower("s1e0r")) {
2458 // SYS #0, C7, C8, #3
2459 SYS_ALIAS(0, 7, 8, 2);
2460 } else if (!Op.compare_lower("s1e0w")) {
2461 // SYS #0, C7, C8, #3
2462 SYS_ALIAS(0, 7, 8, 3);
2463 } else if (!Op.compare_lower("s12e1r")) {
2464 // SYS #4, C7, C8, #4
2465 SYS_ALIAS(4, 7, 8, 4);
2466 } else if (!Op.compare_lower("s12e1w")) {
2467 // SYS #4, C7, C8, #5
2468 SYS_ALIAS(4, 7, 8, 5);
2469 } else if (!Op.compare_lower("s12e0r")) {
2470 // SYS #4, C7, C8, #6
2471 SYS_ALIAS(4, 7, 8, 6);
2472 } else if (!Op.compare_lower("s12e0w")) {
2473 // SYS #4, C7, C8, #7
2474 SYS_ALIAS(4, 7, 8, 7);
Oliver Stannard64c167d2015-11-26 15:34:44 +00002475 } else if (!Op.compare_lower("s1e1rp")) {
2476 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2477 // SYS #0, C7, C9, #0
2478 SYS_ALIAS(0, 7, 9, 0);
2479 } else {
2480 return TokError("AT S1E1RP requires ARMv8.2a");
2481 }
2482 } else if (!Op.compare_lower("s1e1wp")) {
2483 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2484 // SYS #0, C7, C9, #1
2485 SYS_ALIAS(0, 7, 9, 1);
2486 } else {
2487 return TokError("AT S1E1WP requires ARMv8.2a");
2488 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002489 } else {
2490 return TokError("invalid operand for AT instruction");
2491 }
2492 } else if (Mnemonic == "tlbi") {
2493 if (!Op.compare_lower("vmalle1is")) {
2494 // SYS #0, C8, C3, #0
2495 SYS_ALIAS(0, 8, 3, 0);
2496 } else if (!Op.compare_lower("alle2is")) {
2497 // SYS #4, C8, C3, #0
2498 SYS_ALIAS(4, 8, 3, 0);
2499 } else if (!Op.compare_lower("alle3is")) {
2500 // SYS #6, C8, C3, #0
2501 SYS_ALIAS(6, 8, 3, 0);
2502 } else if (!Op.compare_lower("vae1is")) {
2503 // SYS #0, C8, C3, #1
2504 SYS_ALIAS(0, 8, 3, 1);
2505 } else if (!Op.compare_lower("vae2is")) {
2506 // SYS #4, C8, C3, #1
2507 SYS_ALIAS(4, 8, 3, 1);
2508 } else if (!Op.compare_lower("vae3is")) {
2509 // SYS #6, C8, C3, #1
2510 SYS_ALIAS(6, 8, 3, 1);
2511 } else if (!Op.compare_lower("aside1is")) {
2512 // SYS #0, C8, C3, #2
2513 SYS_ALIAS(0, 8, 3, 2);
2514 } else if (!Op.compare_lower("vaae1is")) {
2515 // SYS #0, C8, C3, #3
2516 SYS_ALIAS(0, 8, 3, 3);
2517 } else if (!Op.compare_lower("alle1is")) {
2518 // SYS #4, C8, C3, #4
2519 SYS_ALIAS(4, 8, 3, 4);
2520 } else if (!Op.compare_lower("vale1is")) {
2521 // SYS #0, C8, C3, #5
2522 SYS_ALIAS(0, 8, 3, 5);
2523 } else if (!Op.compare_lower("vaale1is")) {
2524 // SYS #0, C8, C3, #7
2525 SYS_ALIAS(0, 8, 3, 7);
2526 } else if (!Op.compare_lower("vmalle1")) {
2527 // SYS #0, C8, C7, #0
2528 SYS_ALIAS(0, 8, 7, 0);
2529 } else if (!Op.compare_lower("alle2")) {
2530 // SYS #4, C8, C7, #0
2531 SYS_ALIAS(4, 8, 7, 0);
2532 } else if (!Op.compare_lower("vale2is")) {
2533 // SYS #4, C8, C3, #5
2534 SYS_ALIAS(4, 8, 3, 5);
2535 } else if (!Op.compare_lower("vale3is")) {
2536 // SYS #6, C8, C3, #5
2537 SYS_ALIAS(6, 8, 3, 5);
2538 } else if (!Op.compare_lower("alle3")) {
2539 // SYS #6, C8, C7, #0
2540 SYS_ALIAS(6, 8, 7, 0);
2541 } else if (!Op.compare_lower("vae1")) {
2542 // SYS #0, C8, C7, #1
2543 SYS_ALIAS(0, 8, 7, 1);
2544 } else if (!Op.compare_lower("vae2")) {
2545 // SYS #4, C8, C7, #1
2546 SYS_ALIAS(4, 8, 7, 1);
2547 } else if (!Op.compare_lower("vae3")) {
2548 // SYS #6, C8, C7, #1
2549 SYS_ALIAS(6, 8, 7, 1);
2550 } else if (!Op.compare_lower("aside1")) {
2551 // SYS #0, C8, C7, #2
2552 SYS_ALIAS(0, 8, 7, 2);
2553 } else if (!Op.compare_lower("vaae1")) {
2554 // SYS #0, C8, C7, #3
2555 SYS_ALIAS(0, 8, 7, 3);
2556 } else if (!Op.compare_lower("alle1")) {
2557 // SYS #4, C8, C7, #4
2558 SYS_ALIAS(4, 8, 7, 4);
2559 } else if (!Op.compare_lower("vale1")) {
2560 // SYS #0, C8, C7, #5
2561 SYS_ALIAS(0, 8, 7, 5);
2562 } else if (!Op.compare_lower("vale2")) {
2563 // SYS #4, C8, C7, #5
2564 SYS_ALIAS(4, 8, 7, 5);
2565 } else if (!Op.compare_lower("vale3")) {
2566 // SYS #6, C8, C7, #5
2567 SYS_ALIAS(6, 8, 7, 5);
2568 } else if (!Op.compare_lower("vaale1")) {
2569 // SYS #0, C8, C7, #7
2570 SYS_ALIAS(0, 8, 7, 7);
2571 } else if (!Op.compare_lower("ipas2e1")) {
2572 // SYS #4, C8, C4, #1
2573 SYS_ALIAS(4, 8, 4, 1);
2574 } else if (!Op.compare_lower("ipas2le1")) {
2575 // SYS #4, C8, C4, #5
2576 SYS_ALIAS(4, 8, 4, 5);
2577 } else if (!Op.compare_lower("ipas2e1is")) {
2578 // SYS #4, C8, C4, #1
2579 SYS_ALIAS(4, 8, 0, 1);
2580 } else if (!Op.compare_lower("ipas2le1is")) {
2581 // SYS #4, C8, C4, #5
2582 SYS_ALIAS(4, 8, 0, 5);
2583 } else if (!Op.compare_lower("vmalls12e1")) {
2584 // SYS #4, C8, C7, #6
2585 SYS_ALIAS(4, 8, 7, 6);
2586 } else if (!Op.compare_lower("vmalls12e1is")) {
2587 // SYS #4, C8, C3, #6
2588 SYS_ALIAS(4, 8, 3, 6);
2589 } else {
2590 return TokError("invalid operand for TLBI instruction");
2591 }
2592 }
2593
2594#undef SYS_ALIAS
2595
2596 Parser.Lex(); // Eat operand.
2597
2598 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2599 bool HasRegister = false;
2600
2601 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002602 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002603 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2604 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002605 HasRegister = true;
2606 }
2607
Tim Northover3b0846e2014-05-24 12:50:23 +00002608 if (ExpectRegister && !HasRegister) {
2609 return TokError("specified " + Mnemonic + " op requires a register");
2610 }
2611 else if (!ExpectRegister && HasRegister) {
2612 return TokError("specified " + Mnemonic + " op does not use a register");
2613 }
2614
Nirav Davee833c6c2016-11-08 18:31:04 +00002615 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2616 return true;
2617
Tim Northover3b0846e2014-05-24 12:50:23 +00002618 return false;
2619}
2620
Alex Bradbury58eba092016-11-01 16:32:05 +00002621OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002622AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002623 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002624 const AsmToken &Tok = Parser.getTok();
2625
2626 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002627 if (parseOptionalToken(AsmToken::Hash) ||
2628 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002629 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002630 const MCExpr *ImmVal;
2631 SMLoc ExprLoc = getLoc();
2632 if (getParser().parseExpression(ImmVal))
2633 return MatchOperand_ParseFail;
2634 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2635 if (!MCE) {
2636 Error(ExprLoc, "immediate value expected for barrier operand");
2637 return MatchOperand_ParseFail;
2638 }
2639 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2640 Error(ExprLoc, "barrier operand out of range");
2641 return MatchOperand_ParseFail;
2642 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002643 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2644 Operands.push_back(AArch64Operand::CreateBarrier(
2645 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002646 return MatchOperand_Success;
2647 }
2648
2649 if (Tok.isNot(AsmToken::Identifier)) {
2650 TokError("invalid operand for instruction");
2651 return MatchOperand_ParseFail;
2652 }
2653
Tim Northovere6ae6762016-07-05 21:23:04 +00002654 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2655 if (!DB) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002656 TokError("invalid barrier option name");
2657 return MatchOperand_ParseFail;
2658 }
2659
2660 // The only valid named option for ISB is 'sy'
Tim Northovere6ae6762016-07-05 21:23:04 +00002661 if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002662 TokError("'sy' or #imm operand expected");
2663 return MatchOperand_ParseFail;
2664 }
2665
Tim Northovere6ae6762016-07-05 21:23:04 +00002666 Operands.push_back(AArch64Operand::CreateBarrier(
2667 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002668 Parser.Lex(); // Consume the option
2669
2670 return MatchOperand_Success;
2671}
2672
Alex Bradbury58eba092016-11-01 16:32:05 +00002673OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002674AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002675 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002676 const AsmToken &Tok = Parser.getTok();
2677
2678 if (Tok.isNot(AsmToken::Identifier))
2679 return MatchOperand_NoMatch;
2680
Tim Northovere6ae6762016-07-05 21:23:04 +00002681 int MRSReg, MSRReg;
2682 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2683 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2684 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2685 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2686 } else
2687 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002688
Tim Northovere6ae6762016-07-05 21:23:04 +00002689 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2690 unsigned PStateImm = -1;
2691 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2692 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002693
Tim Northovere6ae6762016-07-05 21:23:04 +00002694 Operands.push_back(
2695 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2696 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002697 Parser.Lex(); // Eat identifier
2698
2699 return MatchOperand_Success;
2700}
2701
2702/// tryParseVectorRegister - Parse a vector register operand.
2703bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002704 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002705 if (Parser.getTok().isNot(AsmToken::Identifier))
2706 return true;
2707
2708 SMLoc S = getLoc();
2709 // Check for a vector register specifier first.
2710 StringRef Kind;
2711 int64_t Reg = tryMatchVectorRegister(Kind, false);
2712 if (Reg == -1)
2713 return true;
2714 Operands.push_back(
2715 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2716 // If there was an explicit qualifier, that goes on as a literal text
2717 // operand.
2718 if (!Kind.empty())
2719 Operands.push_back(
2720 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2721
2722 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002723 SMLoc SIdx = getLoc();
2724 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002725 const MCExpr *ImmVal;
2726 if (getParser().parseExpression(ImmVal))
2727 return false;
2728 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2729 if (!MCE) {
2730 TokError("immediate value expected for vector index");
2731 return false;
2732 }
2733
2734 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002735
Nirav Davee833c6c2016-11-08 18:31:04 +00002736 if (parseToken(AsmToken::RBrac, "']' expected"))
2737 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002738
2739 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2740 E, getContext()));
2741 }
2742
2743 return false;
2744}
2745
2746/// parseRegister - Parse a non-vector register operand.
2747bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002748 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002749 SMLoc S = getLoc();
2750 // Try for a vector register.
2751 if (!tryParseVectorRegister(Operands))
2752 return false;
2753
2754 // Try for a scalar register.
2755 int64_t Reg = tryParseRegister();
2756 if (Reg == -1)
2757 return true;
2758 Operands.push_back(
2759 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2760
2761 // A small number of instructions (FMOVXDhighr, for example) have "[1]"
2762 // as a string token in the instruction itself.
Nirav Davee833c6c2016-11-08 18:31:04 +00002763 SMLoc LBracS = getLoc();
2764 const AsmToken &Tok = Parser.getTok();
2765 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002766 if (Tok.is(AsmToken::Integer)) {
2767 SMLoc IntS = getLoc();
2768 int64_t Val = Tok.getIntVal();
2769 if (Val == 1) {
2770 Parser.Lex();
Nirav Davee833c6c2016-11-08 18:31:04 +00002771 SMLoc RBracS = getLoc();
2772 if (parseOptionalToken(AsmToken::RBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002773 Operands.push_back(
2774 AArch64Operand::CreateToken("[", false, LBracS, getContext()));
2775 Operands.push_back(
2776 AArch64Operand::CreateToken("1", false, IntS, getContext()));
2777 Operands.push_back(
2778 AArch64Operand::CreateToken("]", false, RBracS, getContext()));
2779 return false;
2780 }
2781 }
2782 }
2783 }
2784
2785 return false;
2786}
2787
2788bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002789 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002790 bool HasELFModifier = false;
2791 AArch64MCExpr::VariantKind RefKind;
2792
Nirav Davee833c6c2016-11-08 18:31:04 +00002793 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002794 HasELFModifier = true;
2795
Nirav Davee833c6c2016-11-08 18:31:04 +00002796 if (Parser.getTok().isNot(AsmToken::Identifier))
2797 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002798
2799 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2800 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2801 .Case("lo12", AArch64MCExpr::VK_LO12)
2802 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2803 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2804 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2805 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2806 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2807 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2808 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2809 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2810 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2811 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2812 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2813 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2814 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2815 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2816 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2817 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2818 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2819 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2820 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2821 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2822 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2823 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2824 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2825 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2826 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2827 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2828 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2829 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2830 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2831 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2832 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2833 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2834 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2835 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2836 .Default(AArch64MCExpr::VK_INVALID);
2837
Nirav Davee833c6c2016-11-08 18:31:04 +00002838 if (RefKind == AArch64MCExpr::VK_INVALID)
2839 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002840
2841 Parser.Lex(); // Eat identifier
2842
Nirav Davee833c6c2016-11-08 18:31:04 +00002843 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002844 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002845 }
2846
2847 if (getParser().parseExpression(ImmVal))
2848 return true;
2849
2850 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002851 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002852
2853 return false;
2854}
2855
2856/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2857bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002858 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002859 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2860 SMLoc S = getLoc();
2861 Parser.Lex(); // Eat left bracket token.
2862 StringRef Kind;
2863 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2864 if (FirstReg == -1)
2865 return true;
2866 int64_t PrevReg = FirstReg;
2867 unsigned Count = 1;
2868
Nirav Davee833c6c2016-11-08 18:31:04 +00002869 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002870 SMLoc Loc = getLoc();
2871 StringRef NextKind;
2872 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2873 if (Reg == -1)
2874 return true;
2875 // Any Kind suffices must match on all regs in the list.
2876 if (Kind != NextKind)
2877 return Error(Loc, "mismatched register size suffix");
2878
2879 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2880
2881 if (Space == 0 || Space > 3) {
2882 return Error(Loc, "invalid number of vectors");
2883 }
2884
2885 Count += Space;
2886 }
2887 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002888 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002889 SMLoc Loc = getLoc();
2890 StringRef NextKind;
2891 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2892 if (Reg == -1)
2893 return true;
2894 // Any Kind suffices must match on all regs in the list.
2895 if (Kind != NextKind)
2896 return Error(Loc, "mismatched register size suffix");
2897
2898 // Registers must be incremental (with wraparound at 31)
2899 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2900 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2901 return Error(Loc, "registers must be sequential");
2902
2903 PrevReg = Reg;
2904 ++Count;
2905 }
2906 }
2907
Nirav Davee833c6c2016-11-08 18:31:04 +00002908 if (parseToken(AsmToken::RCurly, "'}' expected"))
2909 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002910
2911 if (Count > 4)
2912 return Error(S, "invalid number of vectors");
2913
2914 unsigned NumElements = 0;
2915 char ElementKind = 0;
2916 if (!Kind.empty())
2917 parseValidVectorKind(Kind, NumElements, ElementKind);
2918
2919 Operands.push_back(AArch64Operand::CreateVectorList(
2920 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2921
2922 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002923 SMLoc SIdx = getLoc();
2924 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002925 const MCExpr *ImmVal;
2926 if (getParser().parseExpression(ImmVal))
2927 return false;
2928 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2929 if (!MCE) {
2930 TokError("immediate value expected for vector index");
2931 return false;
2932 }
2933
2934 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002935 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002936 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002937
2938 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2939 E, getContext()));
2940 }
2941 return false;
2942}
2943
Alex Bradbury58eba092016-11-01 16:32:05 +00002944OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002945AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002946 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002947 const AsmToken &Tok = Parser.getTok();
2948 if (!Tok.is(AsmToken::Identifier))
2949 return MatchOperand_NoMatch;
2950
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002951 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00002952
2953 MCContext &Ctx = getContext();
2954 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2955 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2956 return MatchOperand_NoMatch;
2957
2958 SMLoc S = getLoc();
2959 Parser.Lex(); // Eat register
2960
Nirav Davee833c6c2016-11-08 18:31:04 +00002961 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002962 Operands.push_back(
2963 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2964 return MatchOperand_Success;
2965 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002966
Nirav Davee833c6c2016-11-08 18:31:04 +00002967 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002968
2969 if (Parser.getTok().isNot(AsmToken::Integer)) {
2970 Error(getLoc(), "index must be absent or #0");
2971 return MatchOperand_ParseFail;
2972 }
2973
2974 const MCExpr *ImmVal;
2975 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2976 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2977 Error(getLoc(), "index must be absent or #0");
2978 return MatchOperand_ParseFail;
2979 }
2980
2981 Operands.push_back(
2982 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2983 return MatchOperand_Success;
2984}
2985
2986/// parseOperand - Parse a arm instruction operand. For now this parses the
2987/// operand regardless of the mnemonic.
2988bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
2989 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002990 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002991 // Check if the current operand has a custom associated parser, if so, try to
2992 // custom parse the operand, or fallback to the general approach.
2993 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2994 if (ResTy == MatchOperand_Success)
2995 return false;
2996 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2997 // there was a match, but an error occurred, in which case, just return that
2998 // the operand parsing failed.
2999 if (ResTy == MatchOperand_ParseFail)
3000 return true;
3001
3002 // Nothing custom, so do general case parsing.
3003 SMLoc S, E;
3004 switch (getLexer().getKind()) {
3005 default: {
3006 SMLoc S = getLoc();
3007 const MCExpr *Expr;
3008 if (parseSymbolicImmVal(Expr))
3009 return Error(S, "invalid operand");
3010
3011 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3012 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3013 return false;
3014 }
3015 case AsmToken::LBrac: {
3016 SMLoc Loc = Parser.getTok().getLoc();
3017 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3018 getContext()));
3019 Parser.Lex(); // Eat '['
3020
3021 // There's no comma after a '[', so we can parse the next operand
3022 // immediately.
3023 return parseOperand(Operands, false, false);
3024 }
3025 case AsmToken::LCurly:
3026 return parseVectorList(Operands);
3027 case AsmToken::Identifier: {
3028 // If we're expecting a Condition Code operand, then just parse that.
3029 if (isCondCode)
3030 return parseCondCode(Operands, invertCondCode);
3031
3032 // If it's a register name, parse it.
3033 if (!parseRegister(Operands))
3034 return false;
3035
3036 // This could be an optional "shift" or "extend" operand.
3037 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3038 // We can only continue if no tokens were eaten.
3039 if (GotShift != MatchOperand_NoMatch)
3040 return GotShift;
3041
3042 // This was not a register so parse other operands that start with an
3043 // identifier (like labels) as expressions and create them as immediates.
3044 const MCExpr *IdVal;
3045 S = getLoc();
3046 if (getParser().parseExpression(IdVal))
3047 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003048 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3049 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3050 return false;
3051 }
3052 case AsmToken::Integer:
3053 case AsmToken::Real:
3054 case AsmToken::Hash: {
3055 // #42 -> immediate.
3056 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003057
3058 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003059
3060 // Parse a negative sign
3061 bool isNegative = false;
3062 if (Parser.getTok().is(AsmToken::Minus)) {
3063 isNegative = true;
3064 // We need to consume this token only when we have a Real, otherwise
3065 // we let parseSymbolicImmVal take care of it
3066 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3067 Parser.Lex();
3068 }
3069
3070 // The only Real that should come through here is a literal #0.0 for
3071 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3072 // so convert the value.
3073 const AsmToken &Tok = Parser.getTok();
3074 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003075 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003076 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3077 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3078 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3079 Mnemonic != "fcmlt")
3080 return TokError("unexpected floating point literal");
3081 else if (IntVal != 0 || isNegative)
3082 return TokError("expected floating-point constant #0.0");
3083 Parser.Lex(); // Eat the token.
3084
3085 Operands.push_back(
3086 AArch64Operand::CreateToken("#0", false, S, getContext()));
3087 Operands.push_back(
3088 AArch64Operand::CreateToken(".0", false, S, getContext()));
3089 return false;
3090 }
3091
3092 const MCExpr *ImmVal;
3093 if (parseSymbolicImmVal(ImmVal))
3094 return true;
3095
3096 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3097 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3098 return false;
3099 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003100 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003101 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003102 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003103 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003104 Parser.Lex(); // Eat '='
3105 const MCExpr *SubExprVal;
3106 if (getParser().parseExpression(SubExprVal))
3107 return true;
3108
David Peixottoae5ba762014-07-18 16:05:14 +00003109 if (Operands.size() < 2 ||
3110 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003111 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003112
3113 bool IsXReg =
3114 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3115 Operands[1]->getReg());
3116
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003117 MCContext& Ctx = getContext();
3118 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3119 // 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 +00003120 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003121 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3122 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3123 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3124 ShiftAmt += 16;
3125 Imm >>= 16;
3126 }
3127 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3128 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3129 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003130 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003131 if (ShiftAmt)
3132 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3133 ShiftAmt, true, S, E, Ctx));
3134 return false;
3135 }
David Peixottoae5ba762014-07-18 16:05:14 +00003136 APInt Simm = APInt(64, Imm << ShiftAmt);
3137 // check if the immediate is an unsigned or signed 32-bit int for W regs
3138 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3139 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003140 }
3141 // 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 +00003142 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003143 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003144 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3145 return false;
3146 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003147 }
3148}
3149
3150/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3151/// operands.
3152bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3153 StringRef Name, SMLoc NameLoc,
3154 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003155 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003156 Name = StringSwitch<StringRef>(Name.lower())
3157 .Case("beq", "b.eq")
3158 .Case("bne", "b.ne")
3159 .Case("bhs", "b.hs")
3160 .Case("bcs", "b.cs")
3161 .Case("blo", "b.lo")
3162 .Case("bcc", "b.cc")
3163 .Case("bmi", "b.mi")
3164 .Case("bpl", "b.pl")
3165 .Case("bvs", "b.vs")
3166 .Case("bvc", "b.vc")
3167 .Case("bhi", "b.hi")
3168 .Case("bls", "b.ls")
3169 .Case("bge", "b.ge")
3170 .Case("blt", "b.lt")
3171 .Case("bgt", "b.gt")
3172 .Case("ble", "b.le")
3173 .Case("bal", "b.al")
3174 .Case("bnv", "b.nv")
3175 .Default(Name);
3176
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003177 // First check for the AArch64-specific .req directive.
3178 if (Parser.getTok().is(AsmToken::Identifier) &&
3179 Parser.getTok().getIdentifier() == ".req") {
3180 parseDirectiveReq(Name, NameLoc);
3181 // We always return 'error' for this, as we're done with this
3182 // statement and don't need to match the 'instruction."
3183 return true;
3184 }
3185
Tim Northover3b0846e2014-05-24 12:50:23 +00003186 // Create the leading tokens for the mnemonic, split by '.' characters.
3187 size_t Start = 0, Next = Name.find('.');
3188 StringRef Head = Name.slice(Start, Next);
3189
3190 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003191 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3192 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003193
3194 Operands.push_back(
3195 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3196 Mnemonic = Head;
3197
3198 // Handle condition codes for a branch mnemonic
3199 if (Head == "b" && Next != StringRef::npos) {
3200 Start = Next;
3201 Next = Name.find('.', Start + 1);
3202 Head = Name.slice(Start + 1, Next);
3203
3204 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3205 (Head.data() - Name.data()));
3206 AArch64CC::CondCode CC = parseCondCodeString(Head);
3207 if (CC == AArch64CC::Invalid)
3208 return Error(SuffixLoc, "invalid condition code");
3209 Operands.push_back(
3210 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3211 Operands.push_back(
3212 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3213 }
3214
3215 // Add the remaining tokens in the mnemonic.
3216 while (Next != StringRef::npos) {
3217 Start = Next;
3218 Next = Name.find('.', Start + 1);
3219 Head = Name.slice(Start, Next);
3220 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3221 (Head.data() - Name.data()) + 1);
3222 Operands.push_back(
3223 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3224 }
3225
3226 // Conditional compare instructions have a Condition Code operand, which needs
3227 // to be parsed and an immediate operand created.
3228 bool condCodeFourthOperand =
3229 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3230 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3231 Head == "csinc" || Head == "csinv" || Head == "csneg");
3232
3233 // These instructions are aliases to some of the conditional select
3234 // instructions. However, the condition code is inverted in the aliased
3235 // instruction.
3236 //
3237 // FIXME: Is this the correct way to handle these? Or should the parser
3238 // generate the aliased instructions directly?
3239 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3240 bool condCodeThirdOperand =
3241 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3242
3243 // Read the remaining operands.
3244 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3245 // Read the first operand.
3246 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003247 return true;
3248 }
3249
3250 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003251 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003252 // Parse and remember the operand.
3253 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3254 (N == 3 && condCodeThirdOperand) ||
3255 (N == 2 && condCodeSecondOperand),
3256 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003257 return true;
3258 }
3259
3260 // After successfully parsing some operands there are two special cases to
3261 // consider (i.e. notional operands not separated by commas). Both are due
3262 // to memory specifiers:
3263 // + An RBrac will end an address for load/store/prefetch
3264 // + An '!' will indicate a pre-indexed operation.
3265 //
3266 // It's someone else's responsibility to make sure these tokens are sane
3267 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003268
Nirav Davee833c6c2016-11-08 18:31:04 +00003269 SMLoc RLoc = Parser.getTok().getLoc();
3270 if (parseOptionalToken(AsmToken::RBrac))
3271 Operands.push_back(
3272 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3273 SMLoc ELoc = Parser.getTok().getLoc();
3274 if (parseOptionalToken(AsmToken::Exclaim))
3275 Operands.push_back(
3276 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003277
3278 ++N;
3279 }
3280 }
3281
Nirav Davee833c6c2016-11-08 18:31:04 +00003282 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3283 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003284
Tim Northover3b0846e2014-05-24 12:50:23 +00003285 return false;
3286}
3287
3288// FIXME: This entire function is a giant hack to provide us with decent
3289// operand range validation/diagnostics until TableGen/MC can be extended
3290// to support autogeneration of this kind of validation.
3291bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3292 SmallVectorImpl<SMLoc> &Loc) {
3293 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3294 // Check for indexed addressing modes w/ the base register being the
3295 // same as a destination/source register or pair load where
3296 // the Rt == Rt2. All of those are undefined behaviour.
3297 switch (Inst.getOpcode()) {
3298 case AArch64::LDPSWpre:
3299 case AArch64::LDPWpost:
3300 case AArch64::LDPWpre:
3301 case AArch64::LDPXpost:
3302 case AArch64::LDPXpre: {
3303 unsigned Rt = Inst.getOperand(1).getReg();
3304 unsigned Rt2 = Inst.getOperand(2).getReg();
3305 unsigned Rn = Inst.getOperand(3).getReg();
3306 if (RI->isSubRegisterEq(Rn, Rt))
3307 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3308 "is also a destination");
3309 if (RI->isSubRegisterEq(Rn, Rt2))
3310 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3311 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003312 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003313 }
3314 case AArch64::LDPDi:
3315 case AArch64::LDPQi:
3316 case AArch64::LDPSi:
3317 case AArch64::LDPSWi:
3318 case AArch64::LDPWi:
3319 case AArch64::LDPXi: {
3320 unsigned Rt = Inst.getOperand(0).getReg();
3321 unsigned Rt2 = Inst.getOperand(1).getReg();
3322 if (Rt == Rt2)
3323 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3324 break;
3325 }
3326 case AArch64::LDPDpost:
3327 case AArch64::LDPDpre:
3328 case AArch64::LDPQpost:
3329 case AArch64::LDPQpre:
3330 case AArch64::LDPSpost:
3331 case AArch64::LDPSpre:
3332 case AArch64::LDPSWpost: {
3333 unsigned Rt = Inst.getOperand(1).getReg();
3334 unsigned Rt2 = Inst.getOperand(2).getReg();
3335 if (Rt == Rt2)
3336 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3337 break;
3338 }
3339 case AArch64::STPDpost:
3340 case AArch64::STPDpre:
3341 case AArch64::STPQpost:
3342 case AArch64::STPQpre:
3343 case AArch64::STPSpost:
3344 case AArch64::STPSpre:
3345 case AArch64::STPWpost:
3346 case AArch64::STPWpre:
3347 case AArch64::STPXpost:
3348 case AArch64::STPXpre: {
3349 unsigned Rt = Inst.getOperand(1).getReg();
3350 unsigned Rt2 = Inst.getOperand(2).getReg();
3351 unsigned Rn = Inst.getOperand(3).getReg();
3352 if (RI->isSubRegisterEq(Rn, Rt))
3353 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3354 "is also a source");
3355 if (RI->isSubRegisterEq(Rn, Rt2))
3356 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3357 "is also a source");
3358 break;
3359 }
3360 case AArch64::LDRBBpre:
3361 case AArch64::LDRBpre:
3362 case AArch64::LDRHHpre:
3363 case AArch64::LDRHpre:
3364 case AArch64::LDRSBWpre:
3365 case AArch64::LDRSBXpre:
3366 case AArch64::LDRSHWpre:
3367 case AArch64::LDRSHXpre:
3368 case AArch64::LDRSWpre:
3369 case AArch64::LDRWpre:
3370 case AArch64::LDRXpre:
3371 case AArch64::LDRBBpost:
3372 case AArch64::LDRBpost:
3373 case AArch64::LDRHHpost:
3374 case AArch64::LDRHpost:
3375 case AArch64::LDRSBWpost:
3376 case AArch64::LDRSBXpost:
3377 case AArch64::LDRSHWpost:
3378 case AArch64::LDRSHXpost:
3379 case AArch64::LDRSWpost:
3380 case AArch64::LDRWpost:
3381 case AArch64::LDRXpost: {
3382 unsigned Rt = Inst.getOperand(1).getReg();
3383 unsigned Rn = Inst.getOperand(2).getReg();
3384 if (RI->isSubRegisterEq(Rn, Rt))
3385 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3386 "is also a source");
3387 break;
3388 }
3389 case AArch64::STRBBpost:
3390 case AArch64::STRBpost:
3391 case AArch64::STRHHpost:
3392 case AArch64::STRHpost:
3393 case AArch64::STRWpost:
3394 case AArch64::STRXpost:
3395 case AArch64::STRBBpre:
3396 case AArch64::STRBpre:
3397 case AArch64::STRHHpre:
3398 case AArch64::STRHpre:
3399 case AArch64::STRWpre:
3400 case AArch64::STRXpre: {
3401 unsigned Rt = Inst.getOperand(1).getReg();
3402 unsigned Rn = Inst.getOperand(2).getReg();
3403 if (RI->isSubRegisterEq(Rn, Rt))
3404 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3405 "is also a source");
3406 break;
3407 }
3408 }
3409
3410 // Now check immediate ranges. Separate from the above as there is overlap
3411 // in the instructions being checked and this keeps the nested conditionals
3412 // to a minimum.
3413 switch (Inst.getOpcode()) {
3414 case AArch64::ADDSWri:
3415 case AArch64::ADDSXri:
3416 case AArch64::ADDWri:
3417 case AArch64::ADDXri:
3418 case AArch64::SUBSWri:
3419 case AArch64::SUBSXri:
3420 case AArch64::SUBWri:
3421 case AArch64::SUBXri: {
3422 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3423 // some slight duplication here.
3424 if (Inst.getOperand(2).isExpr()) {
3425 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3426 AArch64MCExpr::VariantKind ELFRefKind;
3427 MCSymbolRefExpr::VariantKind DarwinRefKind;
3428 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003429 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3430
3431 // Only allow these with ADDXri.
3432 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3433 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3434 Inst.getOpcode() == AArch64::ADDXri)
3435 return false;
3436
3437 // Only allow these with ADDXri/ADDWri
3438 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3439 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3440 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3441 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3442 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3443 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3444 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3445 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3446 (Inst.getOpcode() == AArch64::ADDXri ||
3447 Inst.getOpcode() == AArch64::ADDWri))
3448 return false;
3449
3450 // Don't allow symbol refs in the immediate field otherwise
3451 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3452 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3453 // 'cmp w0, 'borked')
3454 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003455 }
Diana Picusc93518d2016-10-11 09:17:47 +00003456 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003457 }
3458 return false;
3459 }
3460 default:
3461 return false;
3462 }
3463}
3464
3465bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3466 switch (ErrCode) {
3467 case Match_MissingFeature:
3468 return Error(Loc,
3469 "instruction requires a CPU feature not currently enabled");
3470 case Match_InvalidOperand:
3471 return Error(Loc, "invalid operand for instruction");
3472 case Match_InvalidSuffix:
3473 return Error(Loc, "invalid type suffix for instruction");
3474 case Match_InvalidCondCode:
3475 return Error(Loc, "expected AArch64 condition code");
3476 case Match_AddSubRegExtendSmall:
3477 return Error(Loc,
3478 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3479 case Match_AddSubRegExtendLarge:
3480 return Error(Loc,
3481 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3482 case Match_AddSubSecondSource:
3483 return Error(Loc,
3484 "expected compatible register, symbol or integer in range [0, 4095]");
3485 case Match_LogicalSecondSource:
3486 return Error(Loc, "expected compatible register or logical immediate");
3487 case Match_InvalidMovImm32Shift:
3488 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3489 case Match_InvalidMovImm64Shift:
3490 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3491 case Match_AddSubRegShift32:
3492 return Error(Loc,
3493 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3494 case Match_AddSubRegShift64:
3495 return Error(Loc,
3496 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3497 case Match_InvalidFPImm:
3498 return Error(Loc,
3499 "expected compatible register or floating-point constant");
3500 case Match_InvalidMemoryIndexedSImm9:
3501 return Error(Loc, "index must be an integer in range [-256, 255].");
3502 case Match_InvalidMemoryIndexed4SImm7:
3503 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3504 case Match_InvalidMemoryIndexed8SImm7:
3505 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3506 case Match_InvalidMemoryIndexed16SImm7:
3507 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3508 case Match_InvalidMemoryWExtend8:
3509 return Error(Loc,
3510 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3511 case Match_InvalidMemoryWExtend16:
3512 return Error(Loc,
3513 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3514 case Match_InvalidMemoryWExtend32:
3515 return Error(Loc,
3516 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3517 case Match_InvalidMemoryWExtend64:
3518 return Error(Loc,
3519 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3520 case Match_InvalidMemoryWExtend128:
3521 return Error(Loc,
3522 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3523 case Match_InvalidMemoryXExtend8:
3524 return Error(Loc,
3525 "expected 'lsl' or 'sxtx' with optional shift of #0");
3526 case Match_InvalidMemoryXExtend16:
3527 return Error(Loc,
3528 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3529 case Match_InvalidMemoryXExtend32:
3530 return Error(Loc,
3531 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3532 case Match_InvalidMemoryXExtend64:
3533 return Error(Loc,
3534 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3535 case Match_InvalidMemoryXExtend128:
3536 return Error(Loc,
3537 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3538 case Match_InvalidMemoryIndexed1:
3539 return Error(Loc, "index must be an integer in range [0, 4095].");
3540 case Match_InvalidMemoryIndexed2:
3541 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3542 case Match_InvalidMemoryIndexed4:
3543 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3544 case Match_InvalidMemoryIndexed8:
3545 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3546 case Match_InvalidMemoryIndexed16:
3547 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003548 case Match_InvalidImm0_1:
3549 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003550 case Match_InvalidImm0_7:
3551 return Error(Loc, "immediate must be an integer in range [0, 7].");
3552 case Match_InvalidImm0_15:
3553 return Error(Loc, "immediate must be an integer in range [0, 15].");
3554 case Match_InvalidImm0_31:
3555 return Error(Loc, "immediate must be an integer in range [0, 31].");
3556 case Match_InvalidImm0_63:
3557 return Error(Loc, "immediate must be an integer in range [0, 63].");
3558 case Match_InvalidImm0_127:
3559 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003560 case Match_InvalidImm0_255:
3561 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003562 case Match_InvalidImm0_65535:
3563 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3564 case Match_InvalidImm1_8:
3565 return Error(Loc, "immediate must be an integer in range [1, 8].");
3566 case Match_InvalidImm1_16:
3567 return Error(Loc, "immediate must be an integer in range [1, 16].");
3568 case Match_InvalidImm1_32:
3569 return Error(Loc, "immediate must be an integer in range [1, 32].");
3570 case Match_InvalidImm1_64:
3571 return Error(Loc, "immediate must be an integer in range [1, 64].");
3572 case Match_InvalidIndex1:
3573 return Error(Loc, "expected lane specifier '[1]'");
3574 case Match_InvalidIndexB:
3575 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3576 case Match_InvalidIndexH:
3577 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3578 case Match_InvalidIndexS:
3579 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3580 case Match_InvalidIndexD:
3581 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3582 case Match_InvalidLabel:
3583 return Error(Loc, "expected label or encodable integer pc offset");
3584 case Match_MRS:
3585 return Error(Loc, "expected readable system register");
3586 case Match_MSR:
3587 return Error(Loc, "expected writable system register or pstate");
3588 case Match_MnemonicFail:
3589 return Error(Loc, "unrecognized instruction mnemonic");
3590 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003591 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003592 }
3593}
3594
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003595static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003596
3597bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3598 OperandVector &Operands,
3599 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003600 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003601 bool MatchingInlineAsm) {
3602 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003603 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3604 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003605
David Blaikie960ea3f2014-06-08 16:18:35 +00003606 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003607 unsigned NumOperands = Operands.size();
3608
3609 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003610 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3611 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3612 if (Op2.isReg() && Op3.isImm()) {
3613 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003614 if (Op3CE) {
3615 uint64_t Op3Val = Op3CE->getValue();
3616 uint64_t NewOp3Val = 0;
3617 uint64_t NewOp4Val = 0;
3618 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003619 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003620 NewOp3Val = (32 - Op3Val) & 0x1f;
3621 NewOp4Val = 31 - Op3Val;
3622 } else {
3623 NewOp3Val = (64 - Op3Val) & 0x3f;
3624 NewOp4Val = 63 - Op3Val;
3625 }
3626
Jim Grosbach13760bd2015-05-30 01:25:56 +00003627 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3628 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003629
3630 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003631 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003632 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003633 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3634 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3635 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003636 }
3637 }
Tim Northover03b99f62015-04-30 18:28:58 +00003638 } else if (NumOperands == 4 && Tok == "bfc") {
3639 // FIXME: Horrible hack to handle BFC->BFM alias.
3640 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3641 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3642 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3643
3644 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3645 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3646 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3647
3648 if (LSBCE && WidthCE) {
3649 uint64_t LSB = LSBCE->getValue();
3650 uint64_t Width = WidthCE->getValue();
3651
3652 uint64_t RegWidth = 0;
3653 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3654 Op1.getReg()))
3655 RegWidth = 64;
3656 else
3657 RegWidth = 32;
3658
3659 if (LSB >= RegWidth)
3660 return Error(LSBOp.getStartLoc(),
3661 "expected integer in range [0, 31]");
3662 if (Width < 1 || Width > RegWidth)
3663 return Error(WidthOp.getStartLoc(),
3664 "expected integer in range [1, 32]");
3665
3666 uint64_t ImmR = 0;
3667 if (RegWidth == 32)
3668 ImmR = (32 - LSB) & 0x1f;
3669 else
3670 ImmR = (64 - LSB) & 0x3f;
3671
3672 uint64_t ImmS = Width - 1;
3673
3674 if (ImmR != 0 && ImmS >= ImmR)
3675 return Error(WidthOp.getStartLoc(),
3676 "requested insert overflows register");
3677
Jim Grosbach13760bd2015-05-30 01:25:56 +00003678 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3679 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003680 Operands[0] = AArch64Operand::CreateToken(
3681 "bfm", false, Op.getStartLoc(), getContext());
3682 Operands[2] = AArch64Operand::CreateReg(
3683 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3684 SMLoc(), getContext());
3685 Operands[3] = AArch64Operand::CreateImm(
3686 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3687 Operands.emplace_back(
3688 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3689 WidthOp.getEndLoc(), getContext()));
3690 }
3691 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003692 } else if (NumOperands == 5) {
3693 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3694 // UBFIZ -> UBFM aliases.
3695 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003696 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3697 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3698 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003699
David Blaikie960ea3f2014-06-08 16:18:35 +00003700 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3701 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3702 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003703
3704 if (Op3CE && Op4CE) {
3705 uint64_t Op3Val = Op3CE->getValue();
3706 uint64_t Op4Val = Op4CE->getValue();
3707
3708 uint64_t RegWidth = 0;
3709 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003710 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003711 RegWidth = 64;
3712 else
3713 RegWidth = 32;
3714
3715 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003716 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003717 "expected integer in range [0, 31]");
3718 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003719 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003720 "expected integer in range [1, 32]");
3721
3722 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003723 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003724 NewOp3Val = (32 - Op3Val) & 0x1f;
3725 else
3726 NewOp3Val = (64 - Op3Val) & 0x3f;
3727
3728 uint64_t NewOp4Val = Op4Val - 1;
3729
3730 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003731 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003732 "requested insert overflows register");
3733
3734 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003735 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003736 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003737 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003738 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003739 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003740 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003741 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003742 if (Tok == "bfi")
3743 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003744 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003745 else if (Tok == "sbfiz")
3746 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003747 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003748 else if (Tok == "ubfiz")
3749 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003750 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003751 else
3752 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003753 }
3754 }
3755
3756 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3757 // UBFX -> UBFM aliases.
3758 } else if (NumOperands == 5 &&
3759 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003760 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3761 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3762 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003763
David Blaikie960ea3f2014-06-08 16:18:35 +00003764 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3765 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3766 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003767
3768 if (Op3CE && Op4CE) {
3769 uint64_t Op3Val = Op3CE->getValue();
3770 uint64_t Op4Val = Op4CE->getValue();
3771
3772 uint64_t RegWidth = 0;
3773 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003774 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003775 RegWidth = 64;
3776 else
3777 RegWidth = 32;
3778
3779 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003780 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003781 "expected integer in range [0, 31]");
3782 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003783 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003784 "expected integer in range [1, 32]");
3785
3786 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3787
3788 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003789 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003790 "requested extract overflows register");
3791
3792 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003793 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003794 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003795 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003796 if (Tok == "bfxil")
3797 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003798 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003799 else if (Tok == "sbfx")
3800 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003801 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003802 else if (Tok == "ubfx")
3803 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003804 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003805 else
3806 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003807 }
3808 }
3809 }
3810 }
3811 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3812 // InstAlias can't quite handle this since the reg classes aren't
3813 // subclasses.
3814 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3815 // The source register can be Wn here, but the matcher expects a
3816 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003817 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3818 if (Op.isReg()) {
3819 unsigned Reg = getXRegFromWReg(Op.getReg());
3820 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3821 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003822 }
3823 }
3824 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3825 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003826 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3827 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003828 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003829 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003830 // The source register can be Wn here, but the matcher expects a
3831 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003832 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3833 if (Op.isReg()) {
3834 unsigned Reg = getXRegFromWReg(Op.getReg());
3835 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3836 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003837 }
3838 }
3839 }
3840 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3841 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003842 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3843 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003844 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003845 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003846 // The source register can be Wn here, but the matcher expects a
3847 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003848 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3849 if (Op.isReg()) {
3850 unsigned Reg = getWRegFromXReg(Op.getReg());
3851 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3852 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003853 }
3854 }
3855 }
3856
3857 // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
3858 if (NumOperands == 3 && Tok == "fmov") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003859 AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
3860 AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
3861 if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003862 unsigned zreg =
Oliver Stannardb25914e2015-11-27 13:04:48 +00003863 !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003864 RegOp.getReg())
Tim Northover3b0846e2014-05-24 12:50:23 +00003865 ? AArch64::WZR
3866 : AArch64::XZR;
David Blaikie960ea3f2014-06-08 16:18:35 +00003867 Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
3868 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003869 }
3870 }
3871
3872 MCInst Inst;
3873 // First try to match against the secondary set of tables containing the
3874 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3875 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003876 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003877
3878 // If that fails, try against the alternate table containing long-form NEON:
3879 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003880 if (MatchResult != Match_Success) {
3881 // But first, save the short-form match result: we can use it in case the
3882 // long-form match also fails.
3883 auto ShortFormNEONErrorInfo = ErrorInfo;
3884 auto ShortFormNEONMatchResult = MatchResult;
3885
Tim Northover3b0846e2014-05-24 12:50:23 +00003886 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003887 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003888
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003889 // Now, both matches failed, and the long-form match failed on the mnemonic
3890 // suffix token operand. The short-form match failure is probably more
3891 // relevant: use it instead.
3892 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003893 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003894 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3895 MatchResult = ShortFormNEONMatchResult;
3896 ErrorInfo = ShortFormNEONErrorInfo;
3897 }
3898 }
3899
Tim Northover3b0846e2014-05-24 12:50:23 +00003900 switch (MatchResult) {
3901 case Match_Success: {
3902 // Perform range checking and other semantic validations
3903 SmallVector<SMLoc, 8> OperandLocs;
3904 NumOperands = Operands.size();
3905 for (unsigned i = 1; i < NumOperands; ++i)
3906 OperandLocs.push_back(Operands[i]->getStartLoc());
3907 if (validateInstruction(Inst, OperandLocs))
3908 return true;
3909
3910 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003911 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 return false;
3913 }
3914 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003915 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003916 // Special case the error message for the very common case where only
3917 // a single subtarget feature is missing (neon, e.g.).
3918 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003919 uint64_t Mask = 1;
3920 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3921 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003922 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003923 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003924 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003925 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003926 }
3927 return Error(IDLoc, Msg);
3928 }
3929 case Match_MnemonicFail:
3930 return showMatchError(IDLoc, MatchResult);
3931 case Match_InvalidOperand: {
3932 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003933
Tim Northover26bb14e2014-08-18 11:49:42 +00003934 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003935 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003936 return Error(IDLoc, "too few operands for instruction",
3937 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003938
David Blaikie960ea3f2014-06-08 16:18:35 +00003939 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 if (ErrorLoc == SMLoc())
3941 ErrorLoc = IDLoc;
3942 }
3943 // If the match failed on a suffix token operand, tweak the diagnostic
3944 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003945 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
3946 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00003947 MatchResult = Match_InvalidSuffix;
3948
3949 return showMatchError(ErrorLoc, MatchResult);
3950 }
3951 case Match_InvalidMemoryIndexed1:
3952 case Match_InvalidMemoryIndexed2:
3953 case Match_InvalidMemoryIndexed4:
3954 case Match_InvalidMemoryIndexed8:
3955 case Match_InvalidMemoryIndexed16:
3956 case Match_InvalidCondCode:
3957 case Match_AddSubRegExtendSmall:
3958 case Match_AddSubRegExtendLarge:
3959 case Match_AddSubSecondSource:
3960 case Match_LogicalSecondSource:
3961 case Match_AddSubRegShift32:
3962 case Match_AddSubRegShift64:
3963 case Match_InvalidMovImm32Shift:
3964 case Match_InvalidMovImm64Shift:
3965 case Match_InvalidFPImm:
3966 case Match_InvalidMemoryWExtend8:
3967 case Match_InvalidMemoryWExtend16:
3968 case Match_InvalidMemoryWExtend32:
3969 case Match_InvalidMemoryWExtend64:
3970 case Match_InvalidMemoryWExtend128:
3971 case Match_InvalidMemoryXExtend8:
3972 case Match_InvalidMemoryXExtend16:
3973 case Match_InvalidMemoryXExtend32:
3974 case Match_InvalidMemoryXExtend64:
3975 case Match_InvalidMemoryXExtend128:
3976 case Match_InvalidMemoryIndexed4SImm7:
3977 case Match_InvalidMemoryIndexed8SImm7:
3978 case Match_InvalidMemoryIndexed16SImm7:
3979 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003980 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003981 case Match_InvalidImm0_7:
3982 case Match_InvalidImm0_15:
3983 case Match_InvalidImm0_31:
3984 case Match_InvalidImm0_63:
3985 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003986 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00003987 case Match_InvalidImm0_65535:
3988 case Match_InvalidImm1_8:
3989 case Match_InvalidImm1_16:
3990 case Match_InvalidImm1_32:
3991 case Match_InvalidImm1_64:
3992 case Match_InvalidIndex1:
3993 case Match_InvalidIndexB:
3994 case Match_InvalidIndexH:
3995 case Match_InvalidIndexS:
3996 case Match_InvalidIndexD:
3997 case Match_InvalidLabel:
3998 case Match_MSR:
3999 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004000 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004001 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004002 // Any time we get here, there's nothing fancy to do. Just get the
4003 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004004 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004005 if (ErrorLoc == SMLoc())
4006 ErrorLoc = IDLoc;
4007 return showMatchError(ErrorLoc, MatchResult);
4008 }
4009 }
4010
4011 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004012}
4013
4014/// ParseDirective parses the arm specific directives
4015bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004016 const MCObjectFileInfo::Environment Format =
4017 getContext().getObjectFileInfo()->getObjectFileType();
4018 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4019 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004020
Tim Northover3b0846e2014-05-24 12:50:23 +00004021 StringRef IDVal = DirectiveID.getIdentifier();
4022 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004023 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004024 parseDirectiveArch(Loc);
4025 else if (IDVal == ".cpu")
4026 parseDirectiveCPU(Loc);
4027 else if (IDVal == ".hword")
4028 parseDirectiveWord(2, Loc);
4029 else if (IDVal == ".word")
4030 parseDirectiveWord(4, Loc);
4031 else if (IDVal == ".xword")
4032 parseDirectiveWord(8, Loc);
4033 else if (IDVal == ".tlsdesccall")
4034 parseDirectiveTLSDescCall(Loc);
4035 else if (IDVal == ".ltorg" || IDVal == ".pool")
4036 parseDirectiveLtorg(Loc);
4037 else if (IDVal == ".unreq")
4038 parseDirectiveUnreq(Loc);
4039 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004040 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004041 parseDirectiveInst(Loc);
4042 else
4043 return true;
4044 } else if (IDVal == MCLOHDirectiveName())
4045 parseDirectiveLOH(IDVal, Loc);
4046 else
4047 return true;
4048 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004049}
4050
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004051static const struct {
4052 const char *Name;
4053 const FeatureBitset Features;
4054} ExtensionMap[] = {
4055 { "crc", {AArch64::FeatureCRC} },
4056 { "crypto", {AArch64::FeatureCrypto} },
4057 { "fp", {AArch64::FeatureFPARMv8} },
4058 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004059 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004060 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004061
4062 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004063 { "pan", {} },
4064 { "lor", {} },
4065 { "rdma", {} },
4066 { "profile", {} },
4067};
4068
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004069/// parseDirectiveArch
4070/// ::= .arch token
4071bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4072 SMLoc ArchLoc = getLoc();
4073
4074 StringRef Arch, ExtensionString;
4075 std::tie(Arch, ExtensionString) =
4076 getParser().parseStringToEndOfStatement().trim().split('+');
4077
4078 unsigned ID = AArch64::parseArch(Arch);
Nirav Davee833c6c2016-11-08 18:31:04 +00004079 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
4080 return Error(ArchLoc, "unknown arch name");
4081
4082 if (parseToken(AsmToken::EndOfStatement))
4083 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004084
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004085 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004086 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004087 AArch64::getArchFeatures(ID, AArch64Features);
4088 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4089 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004090
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004091 MCSubtargetInfo &STI = copySTI();
4092 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4093 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4094
4095 SmallVector<StringRef, 4> RequestedExtensions;
4096 if (!ExtensionString.empty())
4097 ExtensionString.split(RequestedExtensions, '+');
4098
4099 FeatureBitset Features = STI.getFeatureBits();
4100 for (auto Name : RequestedExtensions) {
4101 bool EnableFeature = true;
4102
4103 if (Name.startswith_lower("no")) {
4104 EnableFeature = false;
4105 Name = Name.substr(2);
4106 }
4107
4108 for (const auto &Extension : ExtensionMap) {
4109 if (Extension.Name != Name)
4110 continue;
4111
4112 if (Extension.Features.none())
4113 report_fatal_error("unsupported architectural extension: " + Name);
4114
4115 FeatureBitset ToggleFeatures = EnableFeature
4116 ? (~Features & Extension.Features)
4117 : ( Features & Extension.Features);
4118 uint64_t Features =
4119 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4120 setAvailableFeatures(Features);
4121 break;
4122 }
4123 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004124 return false;
4125}
4126
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004127/// parseDirectiveCPU
4128/// ::= .cpu id
4129bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
4130 SMLoc CPULoc = getLoc();
4131
4132 StringRef CPU, ExtensionString;
4133 std::tie(CPU, ExtensionString) =
4134 getParser().parseStringToEndOfStatement().trim().split('+');
4135
Nirav Davee833c6c2016-11-08 18:31:04 +00004136 if (parseToken(AsmToken::EndOfStatement))
4137 return true;
4138
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004139 SmallVector<StringRef, 4> RequestedExtensions;
4140 if (!ExtensionString.empty())
4141 ExtensionString.split(RequestedExtensions, '+');
4142
4143 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4144 // once that is tablegen'ed
4145 if (!getSTI().isCPUStringValid(CPU)) {
4146 Error(CPULoc, "unknown CPU name");
4147 return false;
4148 }
4149
4150 MCSubtargetInfo &STI = copySTI();
4151 STI.setDefaultFeatures(CPU, "");
4152
4153 FeatureBitset Features = STI.getFeatureBits();
4154 for (auto Name : RequestedExtensions) {
4155 bool EnableFeature = true;
4156
4157 if (Name.startswith_lower("no")) {
4158 EnableFeature = false;
4159 Name = Name.substr(2);
4160 }
4161
4162 for (const auto &Extension : ExtensionMap) {
4163 if (Extension.Name != Name)
4164 continue;
4165
4166 if (Extension.Features.none())
4167 report_fatal_error("unsupported architectural extension: " + Name);
4168
4169 FeatureBitset ToggleFeatures = EnableFeature
4170 ? (~Features & Extension.Features)
4171 : ( Features & Extension.Features);
4172 uint64_t Features =
4173 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4174 setAvailableFeatures(Features);
4175
4176 break;
4177 }
4178 }
4179 return false;
4180}
4181
Tim Northover3b0846e2014-05-24 12:50:23 +00004182/// parseDirectiveWord
4183/// ::= .word [ expression (, expression)* ]
4184bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004185 auto parseOp = [&]() -> bool {
4186 const MCExpr *Value;
4187 if (getParser().parseExpression(Value))
4188 return true;
4189 getParser().getStreamer().EmitValue(Value, Size, L);
4190 return false;
4191 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004192
Nirav Davee833c6c2016-11-08 18:31:04 +00004193 if (parseMany(parseOp))
4194 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004195 return false;
4196}
4197
Chad Rosierdcd2a302014-10-22 20:35:57 +00004198/// parseDirectiveInst
4199/// ::= .inst opcode [, ...]
4200bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004201 if (getLexer().is(AsmToken::EndOfStatement))
4202 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004203
Nirav Davee833c6c2016-11-08 18:31:04 +00004204 auto parseOp = [&]() -> bool {
4205 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004206 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004207 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4208 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004209 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004210 if (check(!Value, L, "expected constant expression"))
4211 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004212 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004213 return false;
4214 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004215
Nirav Davee833c6c2016-11-08 18:31:04 +00004216 if (parseMany(parseOp))
4217 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004218 return false;
4219}
4220
Tim Northover3b0846e2014-05-24 12:50:23 +00004221// parseDirectiveTLSDescCall:
4222// ::= .tlsdesccall symbol
4223bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4224 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004225 if (check(getParser().parseIdentifier(Name), L,
4226 "expected symbol after directive") ||
4227 parseToken(AsmToken::EndOfStatement))
4228 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004229
Jim Grosbach6f482002015-05-18 18:43:14 +00004230 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004231 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4232 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004233
4234 MCInst Inst;
4235 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004236 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004237
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004238 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004239 return false;
4240}
4241
4242/// ::= .loh <lohName | lohId> label1, ..., labelN
4243/// The number of arguments depends on the loh identifier.
4244bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004245 MCLOHType Kind;
4246 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4247 if (getParser().getTok().isNot(AsmToken::Integer))
4248 return TokError("expected an identifier or a number in directive");
4249 // We successfully get a numeric value for the identifier.
4250 // Check if it is valid.
4251 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004252 if (Id <= -1U && !isValidMCLOHType(Id))
4253 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004254 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004255 } else {
4256 StringRef Name = getTok().getIdentifier();
4257 // We successfully parse an identifier.
4258 // Check if it is a recognized one.
4259 int Id = MCLOHNameToId(Name);
4260
4261 if (Id == -1)
4262 return TokError("invalid identifier in directive");
4263 Kind = (MCLOHType)Id;
4264 }
4265 // Consume the identifier.
4266 Lex();
4267 // Get the number of arguments of this LOH.
4268 int NbArgs = MCLOHIdToNbArgs(Kind);
4269
4270 assert(NbArgs != -1 && "Invalid number of arguments");
4271
4272 SmallVector<MCSymbol *, 3> Args;
4273 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4274 StringRef Name;
4275 if (getParser().parseIdentifier(Name))
4276 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004277 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004278
4279 if (Idx + 1 == NbArgs)
4280 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004281 if (parseToken(AsmToken::Comma,
4282 "unexpected token in '" + Twine(IDVal) + "' directive"))
4283 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004284 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004285 if (parseToken(AsmToken::EndOfStatement,
4286 "unexpected token in '" + Twine(IDVal) + "' directive"))
4287 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004288
4289 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4290 return false;
4291}
4292
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004293/// parseDirectiveLtorg
4294/// ::= .ltorg | .pool
4295bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004296 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4297 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004298 getTargetStreamer().emitCurrentConstantPool();
4299 return false;
4300}
4301
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004302/// parseDirectiveReq
4303/// ::= name .req registername
4304bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004305 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004306 Parser.Lex(); // Eat the '.req' token.
4307 SMLoc SRegLoc = getLoc();
4308 unsigned RegNum = tryParseRegister();
4309 bool IsVector = false;
4310
4311 if (RegNum == static_cast<unsigned>(-1)) {
4312 StringRef Kind;
4313 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004314 if (!Kind.empty())
4315 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004316 IsVector = true;
4317 }
4318
Nirav Dave2364748a2016-09-16 18:30:20 +00004319 if (RegNum == static_cast<unsigned>(-1))
4320 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004321
4322 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004323 if (parseToken(AsmToken::EndOfStatement,
4324 "unexpected input in .req directive"))
4325 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004326
4327 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004328 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004329 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4330
Nirav Dave2364748a2016-09-16 18:30:20 +00004331 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004332}
4333
4334/// parseDirectiveUneq
4335/// ::= .unreq registername
4336bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004337 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004338 if (getTok().isNot(AsmToken::Identifier))
4339 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004340 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4341 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004342 if (parseToken(AsmToken::EndOfStatement))
4343 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004344 return false;
4345}
4346
Tim Northover3b0846e2014-05-24 12:50:23 +00004347bool
4348AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4349 AArch64MCExpr::VariantKind &ELFRefKind,
4350 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4351 int64_t &Addend) {
4352 ELFRefKind = AArch64MCExpr::VK_INVALID;
4353 DarwinRefKind = MCSymbolRefExpr::VK_None;
4354 Addend = 0;
4355
4356 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4357 ELFRefKind = AE->getKind();
4358 Expr = AE->getSubExpr();
4359 }
4360
4361 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4362 if (SE) {
4363 // It's a simple symbol reference with no addend.
4364 DarwinRefKind = SE->getKind();
4365 return true;
4366 }
4367
4368 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4369 if (!BE)
4370 return false;
4371
4372 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4373 if (!SE)
4374 return false;
4375 DarwinRefKind = SE->getKind();
4376
4377 if (BE->getOpcode() != MCBinaryExpr::Add &&
4378 BE->getOpcode() != MCBinaryExpr::Sub)
4379 return false;
4380
4381 // See if the addend is is a constant, otherwise there's more going
4382 // on here than we can deal with.
4383 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4384 if (!AddendExpr)
4385 return false;
4386
4387 Addend = AddendExpr->getValue();
4388 if (BE->getOpcode() == MCBinaryExpr::Sub)
4389 Addend = -Addend;
4390
4391 // It's some symbol reference + a constant addend, but really
4392 // shouldn't use both Darwin and ELF syntax.
4393 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4394 DarwinRefKind == MCSymbolRefExpr::VK_None;
4395}
4396
4397/// Force static initialization.
4398extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004399 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4400 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4401 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004402}
4403
4404#define GET_REGISTER_MATCHER
4405#define GET_SUBTARGET_FEATURE_NAME
4406#define GET_MATCHER_IMPLEMENTATION
4407#include "AArch64GenAsmMatcher.inc"
4408
4409// Define this matcher function after the auto-generated include so we
4410// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004411unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004412 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004413 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004414 // If the kind is a token for a literal immediate, check if our asm
4415 // operand matches. This is for InstAliases which have a fixed-value
4416 // immediate in the syntax.
4417 int64_t ExpectedVal;
4418 switch (Kind) {
4419 default:
4420 return Match_InvalidOperand;
4421 case MCK__35_0:
4422 ExpectedVal = 0;
4423 break;
4424 case MCK__35_1:
4425 ExpectedVal = 1;
4426 break;
4427 case MCK__35_12:
4428 ExpectedVal = 12;
4429 break;
4430 case MCK__35_16:
4431 ExpectedVal = 16;
4432 break;
4433 case MCK__35_2:
4434 ExpectedVal = 2;
4435 break;
4436 case MCK__35_24:
4437 ExpectedVal = 24;
4438 break;
4439 case MCK__35_3:
4440 ExpectedVal = 3;
4441 break;
4442 case MCK__35_32:
4443 ExpectedVal = 32;
4444 break;
4445 case MCK__35_4:
4446 ExpectedVal = 4;
4447 break;
4448 case MCK__35_48:
4449 ExpectedVal = 48;
4450 break;
4451 case MCK__35_6:
4452 ExpectedVal = 6;
4453 break;
4454 case MCK__35_64:
4455 ExpectedVal = 64;
4456 break;
4457 case MCK__35_8:
4458 ExpectedVal = 8;
4459 break;
4460 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004461 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004462 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004463 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004464 if (!CE)
4465 return Match_InvalidOperand;
4466 if (CE->getValue() == ExpectedVal)
4467 return Match_Success;
4468 return Match_InvalidOperand;
4469}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004470
Alex Bradbury58eba092016-11-01 16:32:05 +00004471OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004472AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4473
4474 SMLoc S = getLoc();
4475
4476 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4477 Error(S, "expected register");
4478 return MatchOperand_ParseFail;
4479 }
4480
4481 int FirstReg = tryParseRegister();
4482 if (FirstReg == -1) {
4483 return MatchOperand_ParseFail;
4484 }
4485 const MCRegisterClass &WRegClass =
4486 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4487 const MCRegisterClass &XRegClass =
4488 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4489
4490 bool isXReg = XRegClass.contains(FirstReg),
4491 isWReg = WRegClass.contains(FirstReg);
4492 if (!isXReg && !isWReg) {
4493 Error(S, "expected first even register of a "
4494 "consecutive same-size even/odd register pair");
4495 return MatchOperand_ParseFail;
4496 }
4497
4498 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4499 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4500
4501 if (FirstEncoding & 0x1) {
4502 Error(S, "expected first even register of a "
4503 "consecutive same-size even/odd register pair");
4504 return MatchOperand_ParseFail;
4505 }
4506
4507 SMLoc M = getLoc();
4508 if (getParser().getTok().isNot(AsmToken::Comma)) {
4509 Error(M, "expected comma");
4510 return MatchOperand_ParseFail;
4511 }
4512 // Eat the comma
4513 getParser().Lex();
4514
4515 SMLoc E = getLoc();
4516 int SecondReg = tryParseRegister();
4517 if (SecondReg ==-1) {
4518 return MatchOperand_ParseFail;
4519 }
4520
Eugene Zelenko049b0172017-01-06 00:30:53 +00004521 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004522 (isXReg && !XRegClass.contains(SecondReg)) ||
4523 (isWReg && !WRegClass.contains(SecondReg))) {
4524 Error(E,"expected second odd register of a "
4525 "consecutive same-size even/odd register pair");
4526 return MatchOperand_ParseFail;
4527 }
Joel Jones504bf332016-10-24 13:37:13 +00004528
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004529 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004530 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004531 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4532 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4533 } else {
4534 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4535 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4536 }
4537
4538 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4539 getContext()));
4540
4541 return MatchOperand_Success;
4542}