blob: 0bbc1acda23a5b48929f348f1cc73978d1aa9b49 [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
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000668 template<int N>
669 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000670 if (!isImm())
671 return false;
672 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
673 if (!MCE)
674 return true;
675 int64_t Val = MCE->getValue();
676 if (Val & 0x3)
677 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000678 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
679 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000680 }
681
682 bool
683 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
684 if (!isImm())
685 return false;
686
687 AArch64MCExpr::VariantKind ELFRefKind;
688 MCSymbolRefExpr::VariantKind DarwinRefKind;
689 int64_t Addend;
690 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
691 DarwinRefKind, Addend)) {
692 return false;
693 }
694 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
695 return false;
696
697 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
698 if (ELFRefKind == AllowedModifiers[i])
699 return Addend == 0;
700 }
701
702 return false;
703 }
704
705 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000706 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000707 }
708
709 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000710 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
711 AArch64MCExpr::VK_TPREL_G2,
712 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000713 }
714
715 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000716 return isMovWSymbol({
717 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000718 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
719 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000720 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000721 }
722
723 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000724 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
725 AArch64MCExpr::VK_TPREL_G0,
726 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000727 }
728
729 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000730 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 }
732
733 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000734 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000735 }
736
737 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000738 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
739 AArch64MCExpr::VK_TPREL_G1_NC,
740 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000741 }
742
743 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000744 return isMovWSymbol(
745 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
746 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000747 }
748
749 template<int RegWidth, int Shift>
750 bool isMOVZMovAlias() const {
751 if (!isImm()) return false;
752
753 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
754 if (!CE) return false;
755 uint64_t Value = CE->getValue();
756
Tim Northoverdaa1c012016-06-16 01:42:25 +0000757 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000758 }
759
760 template<int RegWidth, int Shift>
761 bool isMOVNMovAlias() const {
762 if (!isImm()) return false;
763
764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 uint64_t Value = CE->getValue();
767
Tim Northoverdaa1c012016-06-16 01:42:25 +0000768 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000769 }
770
771 bool isFPImm() const { return Kind == k_FPImm; }
772 bool isBarrier() const { return Kind == k_Barrier; }
773 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000774
Tim Northover3b0846e2014-05-24 12:50:23 +0000775 bool isMRSSystemRegister() const {
776 if (!isSysReg()) return false;
777
Tim Northover7cd58932015-01-22 17:23:04 +0000778 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000779 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000780
Tim Northover3b0846e2014-05-24 12:50:23 +0000781 bool isMSRSystemRegister() const {
782 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000783 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000784 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000785
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000786 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000787 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000788 return (SysReg.PStateField == AArch64PState::PAN ||
789 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000790 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000791
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000792 bool isSystemPStateFieldWithImm0_15() const {
793 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000794 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000795 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000796
Tim Northover3b0846e2014-05-24 12:50:23 +0000797 bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
798 bool isVectorReg() const { return Kind == k_Register && Reg.isVector; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000799
Tim Northover3b0846e2014-05-24 12:50:23 +0000800 bool isVectorRegLo() const {
801 return Kind == k_Register && Reg.isVector &&
802 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
803 Reg.RegNum);
804 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000805
Tim Northover3b0846e2014-05-24 12:50:23 +0000806 bool isGPR32as64() const {
807 return Kind == k_Register && !Reg.isVector &&
808 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
809 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000810
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000811 bool isWSeqPair() const {
812 return Kind == k_Register && !Reg.isVector &&
813 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
814 Reg.RegNum);
815 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000816
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000817 bool isXSeqPair() const {
818 return Kind == k_Register && !Reg.isVector &&
819 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
820 Reg.RegNum);
821 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000822
823 bool isGPR64sp0() const {
824 return Kind == k_Register && !Reg.isVector &&
825 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
826 }
827
828 /// Is this a vector list with the type implicit (presumably attached to the
829 /// instruction itself)?
830 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
831 return Kind == k_VectorList && VectorList.Count == NumRegs &&
832 !VectorList.ElementKind;
833 }
834
835 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
836 bool isTypedVectorList() const {
837 if (Kind != k_VectorList)
838 return false;
839 if (VectorList.Count != NumRegs)
840 return false;
841 if (VectorList.ElementKind != ElementKind)
842 return false;
843 return VectorList.NumElements == NumElements;
844 }
845
846 bool isVectorIndex1() const {
847 return Kind == k_VectorIndex && VectorIndex.Val == 1;
848 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000849
Tim Northover3b0846e2014-05-24 12:50:23 +0000850 bool isVectorIndexB() const {
851 return Kind == k_VectorIndex && VectorIndex.Val < 16;
852 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000853
Tim Northover3b0846e2014-05-24 12:50:23 +0000854 bool isVectorIndexH() const {
855 return Kind == k_VectorIndex && VectorIndex.Val < 8;
856 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000857
Tim Northover3b0846e2014-05-24 12:50:23 +0000858 bool isVectorIndexS() const {
859 return Kind == k_VectorIndex && VectorIndex.Val < 4;
860 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000861
Tim Northover3b0846e2014-05-24 12:50:23 +0000862 bool isVectorIndexD() const {
863 return Kind == k_VectorIndex && VectorIndex.Val < 2;
864 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000865
Tim Northover3b0846e2014-05-24 12:50:23 +0000866 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000867
Tim Northover3b0846e2014-05-24 12:50:23 +0000868 bool isTokenEqual(StringRef Str) const {
869 return Kind == k_Token && getToken() == Str;
870 }
871 bool isSysCR() const { return Kind == k_SysCR; }
872 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000873 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000874 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
875 bool isShifter() const {
876 if (!isShiftExtend())
877 return false;
878
879 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
880 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
881 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
882 ST == AArch64_AM::MSL);
883 }
884 bool isExtend() const {
885 if (!isShiftExtend())
886 return false;
887
888 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
889 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
890 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
891 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
892 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
893 ET == AArch64_AM::LSL) &&
894 getShiftExtendAmount() <= 4;
895 }
896
897 bool isExtend64() const {
898 if (!isExtend())
899 return false;
900 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
901 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
902 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
903 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000904
Tim Northover3b0846e2014-05-24 12:50:23 +0000905 bool isExtendLSL64() const {
906 if (!isExtend())
907 return false;
908 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
909 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
910 ET == AArch64_AM::LSL) &&
911 getShiftExtendAmount() <= 4;
912 }
913
914 template<int Width> bool isMemXExtend() const {
915 if (!isExtend())
916 return false;
917 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
918 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
919 (getShiftExtendAmount() == Log2_32(Width / 8) ||
920 getShiftExtendAmount() == 0);
921 }
922
923 template<int Width> bool isMemWExtend() const {
924 if (!isExtend())
925 return false;
926 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
927 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
928 (getShiftExtendAmount() == Log2_32(Width / 8) ||
929 getShiftExtendAmount() == 0);
930 }
931
932 template <unsigned width>
933 bool isArithmeticShifter() const {
934 if (!isShifter())
935 return false;
936
937 // An arithmetic shifter is LSL, LSR, or ASR.
938 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
939 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
940 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
941 }
942
943 template <unsigned width>
944 bool isLogicalShifter() const {
945 if (!isShifter())
946 return false;
947
948 // A logical shifter is LSL, LSR, ASR or ROR.
949 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
950 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
951 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
952 getShiftExtendAmount() < width;
953 }
954
955 bool isMovImm32Shifter() const {
956 if (!isShifter())
957 return false;
958
959 // A MOVi shifter is LSL of 0, 16, 32, or 48.
960 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
961 if (ST != AArch64_AM::LSL)
962 return false;
963 uint64_t Val = getShiftExtendAmount();
964 return (Val == 0 || Val == 16);
965 }
966
967 bool isMovImm64Shifter() const {
968 if (!isShifter())
969 return false;
970
971 // A MOVi shifter is LSL of 0 or 16.
972 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
973 if (ST != AArch64_AM::LSL)
974 return false;
975 uint64_t Val = getShiftExtendAmount();
976 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
977 }
978
979 bool isLogicalVecShifter() const {
980 if (!isShifter())
981 return false;
982
983 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
984 unsigned Shift = getShiftExtendAmount();
985 return getShiftExtendType() == AArch64_AM::LSL &&
986 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
987 }
988
989 bool isLogicalVecHalfWordShifter() const {
990 if (!isLogicalVecShifter())
991 return false;
992
993 // A logical vector shifter is a left shift by 0 or 8.
994 unsigned Shift = getShiftExtendAmount();
995 return getShiftExtendType() == AArch64_AM::LSL &&
996 (Shift == 0 || Shift == 8);
997 }
998
999 bool isMoveVecShifter() const {
1000 if (!isShiftExtend())
1001 return false;
1002
1003 // A logical vector shifter is a left shift by 8 or 16.
1004 unsigned Shift = getShiftExtendAmount();
1005 return getShiftExtendType() == AArch64_AM::MSL &&
1006 (Shift == 8 || Shift == 16);
1007 }
1008
1009 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1010 // to LDUR/STUR when the offset is not legal for the former but is for
1011 // the latter. As such, in addition to checking for being a legal unscaled
1012 // address, also check that it is not a legal scaled address. This avoids
1013 // ambiguity in the matcher.
1014 template<int Width>
1015 bool isSImm9OffsetFB() const {
1016 return isSImm9() && !isUImm12Offset<Width / 8>();
1017 }
1018
1019 bool isAdrpLabel() const {
1020 // Validation was handled during parsing, so we just sanity check that
1021 // something didn't go haywire.
1022 if (!isImm())
1023 return false;
1024
1025 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1026 int64_t Val = CE->getValue();
1027 int64_t Min = - (4096 * (1LL << (21 - 1)));
1028 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1029 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1030 }
1031
1032 return true;
1033 }
1034
1035 bool isAdrLabel() const {
1036 // Validation was handled during parsing, so we just sanity check that
1037 // something didn't go haywire.
1038 if (!isImm())
1039 return false;
1040
1041 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1042 int64_t Val = CE->getValue();
1043 int64_t Min = - (1LL << (21 - 1));
1044 int64_t Max = ((1LL << (21 - 1)) - 1);
1045 return Val >= Min && Val <= Max;
1046 }
1047
1048 return true;
1049 }
1050
1051 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1052 // Add as immediates when possible. Null MCExpr = 0.
1053 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001054 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001055 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001056 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001057 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001058 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001059 }
1060
1061 void addRegOperands(MCInst &Inst, unsigned N) const {
1062 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001063 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001064 }
1065
1066 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1067 assert(N == 1 && "Invalid number of operands!");
1068 assert(
1069 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1070
1071 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1072 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1073 RI->getEncodingValue(getReg()));
1074
Jim Grosbache9119e42015-05-13 18:37:00 +00001075 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001076 }
1077
1078 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1079 assert(N == 1 && "Invalid number of operands!");
1080 assert(
1081 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001082 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001083 }
1084
1085 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1086 assert(N == 1 && "Invalid number of operands!");
1087 assert(
1088 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001089 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001090 }
1091
1092 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001094 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001095 }
1096
1097 template <unsigned NumRegs>
1098 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1099 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001100 static const unsigned FirstRegs[] = { AArch64::D0,
1101 AArch64::D0_D1,
1102 AArch64::D0_D1_D2,
1103 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001104 unsigned FirstReg = FirstRegs[NumRegs - 1];
1105
1106 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001107 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001108 }
1109
1110 template <unsigned NumRegs>
1111 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001113 static const unsigned FirstRegs[] = { AArch64::Q0,
1114 AArch64::Q0_Q1,
1115 AArch64::Q0_Q1_Q2,
1116 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001117 unsigned FirstReg = FirstRegs[NumRegs - 1];
1118
1119 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001120 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001121 }
1122
1123 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1124 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001125 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001126 }
1127
1128 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1129 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001130 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001131 }
1132
1133 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1134 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001135 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001136 }
1137
1138 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1139 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001140 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001141 }
1142
1143 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001145 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001146 }
1147
1148 void addImmOperands(MCInst &Inst, unsigned N) const {
1149 assert(N == 1 && "Invalid number of operands!");
1150 // If this is a pageoff symrefexpr with an addend, adjust the addend
1151 // to be only the page-offset portion. Otherwise, just add the expr
1152 // as-is.
1153 addExpr(Inst, getImm());
1154 }
1155
1156 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1157 assert(N == 2 && "Invalid number of operands!");
1158 if (isShiftedImm()) {
1159 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001160 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001161 } else {
1162 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001163 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001164 }
1165 }
1166
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001167 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1168 assert(N == 2 && "Invalid number of operands!");
1169
1170 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1171 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1172 int64_t Val = -CE->getValue();
1173 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1174
1175 Inst.addOperand(MCOperand::createImm(Val));
1176 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1177 }
1178
Tim Northover3b0846e2014-05-24 12:50:23 +00001179 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001181 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 }
1183
1184 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1187 if (!MCE)
1188 addExpr(Inst, getImm());
1189 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001190 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001191 }
1192
1193 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1194 addImmOperands(Inst, N);
1195 }
1196
1197 template<int Scale>
1198 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1199 assert(N == 1 && "Invalid number of operands!");
1200 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1201
1202 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001203 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001204 return;
1205 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001206 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001207 }
1208
1209 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1210 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001211 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001212 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001213 }
1214
1215 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1216 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001217 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001218 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001219 }
1220
1221 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1222 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001223 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001224 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001225 }
1226
1227 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1228 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001229 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001230 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001231 }
1232
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001233 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1234 assert(N == 1 && "Invalid number of operands!");
1235 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1236 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1237 }
1238
Tim Northover3b0846e2014-05-24 12:50:23 +00001239 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1240 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001241 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001242 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001243 }
1244
1245 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1246 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001247 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001248 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001249 }
1250
1251 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1252 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001253 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001254 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001255 }
1256
1257 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1258 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001259 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001260 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001261 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001262 }
1263
1264 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1265 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001266 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001267 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001268 }
1269
1270 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1271 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001272 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001273 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001274 }
1275
1276 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001278 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001279 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001280 }
1281
1282 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1283 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001284 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001285 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001286 }
1287
1288 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1289 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001290 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001291 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001292 }
1293
1294 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1295 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001296 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001297 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001298 }
1299
1300 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1301 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001302 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001303 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001304 }
1305
1306 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1307 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001308 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001309 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001310 }
1311
1312 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1313 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001314 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001315 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001316 }
1317
1318 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1319 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001320 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001321 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001322 }
1323
1324 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1325 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001326 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001327 uint64_t encoding =
1328 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001329 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001330 }
1331
1332 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1333 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001334 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001335 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001336 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001337 }
1338
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001339 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1340 assert(N == 1 && "Invalid number of operands!");
1341 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1342 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1343 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001344 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001345 }
1346
1347 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1348 assert(N == 1 && "Invalid number of operands!");
1349 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1350 uint64_t encoding =
1351 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001352 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001353 }
1354
Tim Northover3b0846e2014-05-24 12:50:23 +00001355 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1356 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001357 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001358 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001359 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001360 }
1361
1362 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1363 // Branch operands don't encode the low bits, so shift them off
1364 // here. If it's a label, however, just put it on directly as there's
1365 // not enough information now to do anything.
1366 assert(N == 1 && "Invalid number of operands!");
1367 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1368 if (!MCE) {
1369 addExpr(Inst, getImm());
1370 return;
1371 }
1372 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001373 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 }
1375
1376 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1377 // Branch operands don't encode the low bits, so shift them off
1378 // here. If it's a label, however, just put it on directly as there's
1379 // not enough information now to do anything.
1380 assert(N == 1 && "Invalid number of operands!");
1381 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1382 if (!MCE) {
1383 addExpr(Inst, getImm());
1384 return;
1385 }
1386 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001387 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001388 }
1389
1390 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1391 // Branch operands don't encode the low bits, so shift them off
1392 // here. If it's a label, however, just put it on directly as there's
1393 // not enough information now to do anything.
1394 assert(N == 1 && "Invalid number of operands!");
1395 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1396 if (!MCE) {
1397 addExpr(Inst, getImm());
1398 return;
1399 }
1400 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001401 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001402 }
1403
1404 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001406 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001407 }
1408
1409 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001411 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001412 }
1413
1414 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
1416
Jim Grosbache9119e42015-05-13 18:37:00 +00001417 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001418 }
1419
1420 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1421 assert(N == 1 && "Invalid number of operands!");
1422
Jim Grosbache9119e42015-05-13 18:37:00 +00001423 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001424 }
1425
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001426 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1427 assert(N == 1 && "Invalid number of operands!");
1428
1429 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1430 }
1431
1432 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001433 assert(N == 1 && "Invalid number of operands!");
1434
Jim Grosbache9119e42015-05-13 18:37:00 +00001435 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001436 }
1437
1438 void addSysCROperands(MCInst &Inst, unsigned N) const {
1439 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001440 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001441 }
1442
1443 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1444 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001445 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001446 }
1447
Oliver Stannarda34e4702015-12-01 10:48:51 +00001448 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1449 assert(N == 1 && "Invalid number of operands!");
1450 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1451 }
1452
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 void addShifterOperands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455 unsigned Imm =
1456 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001457 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 }
1459
1460 void addExtendOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1463 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1464 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001465 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001466 }
1467
1468 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1469 assert(N == 1 && "Invalid number of operands!");
1470 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1471 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1472 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001473 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001474 }
1475
1476 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1477 assert(N == 2 && "Invalid number of operands!");
1478 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1479 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001480 Inst.addOperand(MCOperand::createImm(IsSigned));
1481 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
1484 // For 8-bit load/store instructions with a register offset, both the
1485 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1486 // they're disambiguated by whether the shift was explicit or implicit rather
1487 // than its size.
1488 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1489 assert(N == 2 && "Invalid number of operands!");
1490 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1491 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001492 Inst.addOperand(MCOperand::createImm(IsSigned));
1493 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001494 }
1495
1496 template<int Shift>
1497 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1498 assert(N == 1 && "Invalid number of operands!");
1499
1500 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1501 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001502 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001503 }
1504
1505 template<int Shift>
1506 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508
1509 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1510 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001511 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001512 }
1513
1514 void print(raw_ostream &OS) const override;
1515
David Blaikie960ea3f2014-06-08 16:18:35 +00001516 static std::unique_ptr<AArch64Operand>
1517 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1518 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001519 Op->Tok.Data = Str.data();
1520 Op->Tok.Length = Str.size();
1521 Op->Tok.IsSuffix = IsSuffix;
1522 Op->StartLoc = S;
1523 Op->EndLoc = S;
1524 return Op;
1525 }
1526
David Blaikie960ea3f2014-06-08 16:18:35 +00001527 static std::unique_ptr<AArch64Operand>
1528 CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
1529 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 Op->Reg.RegNum = RegNum;
1531 Op->Reg.isVector = isVector;
1532 Op->StartLoc = S;
1533 Op->EndLoc = E;
1534 return Op;
1535 }
1536
David Blaikie960ea3f2014-06-08 16:18:35 +00001537 static std::unique_ptr<AArch64Operand>
1538 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1539 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1540 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001541 Op->VectorList.RegNum = RegNum;
1542 Op->VectorList.Count = Count;
1543 Op->VectorList.NumElements = NumElements;
1544 Op->VectorList.ElementKind = ElementKind;
1545 Op->StartLoc = S;
1546 Op->EndLoc = E;
1547 return Op;
1548 }
1549
David Blaikie960ea3f2014-06-08 16:18:35 +00001550 static std::unique_ptr<AArch64Operand>
1551 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1552 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001553 Op->VectorIndex.Val = Idx;
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> CreateImm(const MCExpr *Val, SMLoc S,
1560 SMLoc E, MCContext &Ctx) {
1561 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001562 Op->Imm.Val = Val;
1563 Op->StartLoc = S;
1564 Op->EndLoc = E;
1565 return Op;
1566 }
1567
David Blaikie960ea3f2014-06-08 16:18:35 +00001568 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1569 unsigned ShiftAmount,
1570 SMLoc S, SMLoc E,
1571 MCContext &Ctx) {
1572 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001573 Op->ShiftedImm .Val = Val;
1574 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1575 Op->StartLoc = S;
1576 Op->EndLoc = E;
1577 return Op;
1578 }
1579
David Blaikie960ea3f2014-06-08 16:18:35 +00001580 static std::unique_ptr<AArch64Operand>
1581 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1582 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001583 Op->CondCode.Code = Code;
1584 Op->StartLoc = S;
1585 Op->EndLoc = E;
1586 return Op;
1587 }
1588
David Blaikie960ea3f2014-06-08 16:18:35 +00001589 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1590 MCContext &Ctx) {
1591 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001592 Op->FPImm.Val = Val;
1593 Op->StartLoc = S;
1594 Op->EndLoc = S;
1595 return Op;
1596 }
1597
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001598 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1599 StringRef Str,
1600 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001601 MCContext &Ctx) {
1602 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001603 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001604 Op->Barrier.Data = Str.data();
1605 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001606 Op->StartLoc = S;
1607 Op->EndLoc = S;
1608 return Op;
1609 }
1610
Tim Northover7cd58932015-01-22 17:23:04 +00001611 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1612 uint32_t MRSReg,
1613 uint32_t MSRReg,
1614 uint32_t PStateField,
1615 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001616 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001617 Op->SysReg.Data = Str.data();
1618 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001619 Op->SysReg.MRSReg = MRSReg;
1620 Op->SysReg.MSRReg = MSRReg;
1621 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001622 Op->StartLoc = S;
1623 Op->EndLoc = S;
1624 return Op;
1625 }
1626
David Blaikie960ea3f2014-06-08 16:18:35 +00001627 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1628 SMLoc E, MCContext &Ctx) {
1629 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001630 Op->SysCRImm.Val = Val;
1631 Op->StartLoc = S;
1632 Op->EndLoc = E;
1633 return Op;
1634 }
1635
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001636 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1637 StringRef Str,
1638 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001639 MCContext &Ctx) {
1640 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001641 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001642 Op->Barrier.Data = Str.data();
1643 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001644 Op->StartLoc = S;
1645 Op->EndLoc = S;
1646 return Op;
1647 }
1648
Oliver Stannarda34e4702015-12-01 10:48:51 +00001649 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1650 StringRef Str,
1651 SMLoc S,
1652 MCContext &Ctx) {
1653 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1654 Op->PSBHint.Val = Val;
1655 Op->PSBHint.Data = Str.data();
1656 Op->PSBHint.Length = Str.size();
1657 Op->StartLoc = S;
1658 Op->EndLoc = S;
1659 return Op;
1660 }
1661
David Blaikie960ea3f2014-06-08 16:18:35 +00001662 static std::unique_ptr<AArch64Operand>
1663 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1664 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1665 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001666 Op->ShiftExtend.Type = ShOp;
1667 Op->ShiftExtend.Amount = Val;
1668 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1669 Op->StartLoc = S;
1670 Op->EndLoc = E;
1671 return Op;
1672 }
1673};
1674
1675} // end anonymous namespace.
1676
1677void AArch64Operand::print(raw_ostream &OS) const {
1678 switch (Kind) {
1679 case k_FPImm:
1680 OS << "<fpimm " << getFPImm() << "("
1681 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1682 break;
1683 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001684 StringRef Name = getBarrierName();
1685 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001686 OS << "<barrier " << Name << ">";
1687 else
1688 OS << "<barrier invalid #" << getBarrier() << ">";
1689 break;
1690 }
1691 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001692 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001693 break;
1694 case k_ShiftedImm: {
1695 unsigned Shift = getShiftedImmShift();
1696 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001697 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001698 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1699 break;
1700 }
1701 case k_CondCode:
1702 OS << "<condcode " << getCondCode() << ">";
1703 break;
1704 case k_Register:
1705 OS << "<register " << getReg() << ">";
1706 break;
1707 case k_VectorList: {
1708 OS << "<vectorlist ";
1709 unsigned Reg = getVectorListStart();
1710 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1711 OS << Reg + i << " ";
1712 OS << ">";
1713 break;
1714 }
1715 case k_VectorIndex:
1716 OS << "<vectorindex " << getVectorIndex() << ">";
1717 break;
1718 case k_SysReg:
1719 OS << "<sysreg: " << getSysReg() << '>';
1720 break;
1721 case k_Token:
1722 OS << "'" << getToken() << "'";
1723 break;
1724 case k_SysCR:
1725 OS << "c" << getSysCR();
1726 break;
1727 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001728 StringRef Name = getPrefetchName();
1729 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001730 OS << "<prfop " << Name << ">";
1731 else
1732 OS << "<prfop invalid #" << getPrefetch() << ">";
1733 break;
1734 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001735 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001736 OS << getPSBHintName();
1737 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001738 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001739 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1740 << getShiftExtendAmount();
1741 if (!hasShiftExtendAmount())
1742 OS << "<imp>";
1743 OS << '>';
1744 break;
1745 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001746}
1747
1748/// @name Auto-generated Match Functions
1749/// {
1750
1751static unsigned MatchRegisterName(StringRef Name);
1752
1753/// }
1754
1755static unsigned matchVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001756 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001757 .Case("v0", AArch64::Q0)
1758 .Case("v1", AArch64::Q1)
1759 .Case("v2", AArch64::Q2)
1760 .Case("v3", AArch64::Q3)
1761 .Case("v4", AArch64::Q4)
1762 .Case("v5", AArch64::Q5)
1763 .Case("v6", AArch64::Q6)
1764 .Case("v7", AArch64::Q7)
1765 .Case("v8", AArch64::Q8)
1766 .Case("v9", AArch64::Q9)
1767 .Case("v10", AArch64::Q10)
1768 .Case("v11", AArch64::Q11)
1769 .Case("v12", AArch64::Q12)
1770 .Case("v13", AArch64::Q13)
1771 .Case("v14", AArch64::Q14)
1772 .Case("v15", AArch64::Q15)
1773 .Case("v16", AArch64::Q16)
1774 .Case("v17", AArch64::Q17)
1775 .Case("v18", AArch64::Q18)
1776 .Case("v19", AArch64::Q19)
1777 .Case("v20", AArch64::Q20)
1778 .Case("v21", AArch64::Q21)
1779 .Case("v22", AArch64::Q22)
1780 .Case("v23", AArch64::Q23)
1781 .Case("v24", AArch64::Q24)
1782 .Case("v25", AArch64::Q25)
1783 .Case("v26", AArch64::Q26)
1784 .Case("v27", AArch64::Q27)
1785 .Case("v28", AArch64::Q28)
1786 .Case("v29", AArch64::Q29)
1787 .Case("v30", AArch64::Q30)
1788 .Case("v31", AArch64::Q31)
1789 .Default(0);
1790}
1791
1792static bool isValidVectorKind(StringRef Name) {
1793 return StringSwitch<bool>(Name.lower())
1794 .Case(".8b", true)
1795 .Case(".16b", true)
1796 .Case(".4h", true)
1797 .Case(".8h", true)
1798 .Case(".2s", true)
1799 .Case(".4s", true)
1800 .Case(".1d", true)
1801 .Case(".2d", true)
1802 .Case(".1q", true)
1803 // Accept the width neutral ones, too, for verbose syntax. If those
1804 // aren't used in the right places, the token operand won't match so
1805 // all will work out.
1806 .Case(".b", true)
1807 .Case(".h", true)
1808 .Case(".s", true)
1809 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001810 // Needed for fp16 scalar pairwise reductions
1811 .Case(".2h", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001812 .Default(false);
1813}
1814
1815static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1816 char &ElementKind) {
1817 assert(isValidVectorKind(Name));
1818
1819 ElementKind = Name.lower()[Name.size() - 1];
1820 NumElements = 0;
1821
1822 if (Name.size() == 2)
1823 return;
1824
1825 // Parse the lane count
1826 Name = Name.drop_front();
1827 while (isdigit(Name.front())) {
1828 NumElements = 10 * NumElements + (Name.front() - '0');
1829 Name = Name.drop_front();
1830 }
1831}
1832
1833bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1834 SMLoc &EndLoc) {
1835 StartLoc = getLoc();
1836 RegNo = tryParseRegister();
1837 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1838 return (RegNo == (unsigned)-1);
1839}
1840
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001841// Matches a register name or register alias previously defined by '.req'
1842unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
1843 bool isVector) {
1844 unsigned RegNum = isVector ? matchVectorRegName(Name)
1845 : MatchRegisterName(Name);
1846
1847 if (RegNum == 0) {
1848 // Check for aliases registered via .req. Canonicalize to lower case.
1849 // That's more consistent since register names are case insensitive, and
1850 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1851 auto Entry = RegisterReqs.find(Name.lower());
1852 if (Entry == RegisterReqs.end())
1853 return 0;
1854 // set RegNum if the match is the right kind of register
1855 if (isVector == Entry->getValue().first)
1856 RegNum = Entry->getValue().second;
1857 }
1858 return RegNum;
1859}
1860
Tim Northover3b0846e2014-05-24 12:50:23 +00001861/// tryParseRegister - Try to parse a register name. The token must be an
1862/// Identifier when called, and if it is a register name the token is eaten and
1863/// the register is added to the operand list.
1864int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001865 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001866 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001867 if (Tok.isNot(AsmToken::Identifier))
1868 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00001869
1870 std::string lowerCase = Tok.getString().lower();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001871 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
Tim Northover3b0846e2014-05-24 12:50:23 +00001872 // Also handle a few aliases of registers.
1873 if (RegNum == 0)
1874 RegNum = StringSwitch<unsigned>(lowerCase)
1875 .Case("fp", AArch64::FP)
1876 .Case("lr", AArch64::LR)
1877 .Case("x31", AArch64::XZR)
1878 .Case("w31", AArch64::WZR)
1879 .Default(0);
1880
1881 if (RegNum == 0)
1882 return -1;
1883
1884 Parser.Lex(); // Eat identifier token.
1885 return RegNum;
1886}
1887
1888/// tryMatchVectorRegister - Try to parse a vector register name with optional
1889/// kind specifier. If it is a register specifier, eat the token and return it.
1890int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001891 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001892 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1893 TokError("vector register expected");
1894 return -1;
1895 }
1896
1897 StringRef Name = Parser.getTok().getString();
1898 // If there is a kind specifier, it's separated from the register name by
1899 // a '.'.
1900 size_t Start = 0, Next = Name.find('.');
1901 StringRef Head = Name.slice(Start, Next);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001902 unsigned RegNum = matchRegisterNameAlias(Head, true);
1903
Tim Northover3b0846e2014-05-24 12:50:23 +00001904 if (RegNum) {
1905 if (Next != StringRef::npos) {
1906 Kind = Name.slice(Next, StringRef::npos);
1907 if (!isValidVectorKind(Kind)) {
1908 TokError("invalid vector kind qualifier");
1909 return -1;
1910 }
1911 }
1912 Parser.Lex(); // Eat the register token.
1913 return RegNum;
1914 }
1915
1916 if (expected)
1917 TokError("vector register expected");
1918 return -1;
1919}
1920
1921/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00001922OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001923AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001924 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001925 SMLoc S = getLoc();
1926
1927 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1928 Error(S, "Expected cN operand where 0 <= N <= 15");
1929 return MatchOperand_ParseFail;
1930 }
1931
1932 StringRef Tok = Parser.getTok().getIdentifier();
1933 if (Tok[0] != 'c' && Tok[0] != 'C') {
1934 Error(S, "Expected cN operand where 0 <= N <= 15");
1935 return MatchOperand_ParseFail;
1936 }
1937
1938 uint32_t CRNum;
1939 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
1940 if (BadNum || CRNum > 15) {
1941 Error(S, "Expected cN operand where 0 <= N <= 15");
1942 return MatchOperand_ParseFail;
1943 }
1944
1945 Parser.Lex(); // Eat identifier token.
1946 Operands.push_back(
1947 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
1948 return MatchOperand_Success;
1949}
1950
1951/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00001952OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001953AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001954 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001955 SMLoc S = getLoc();
1956 const AsmToken &Tok = Parser.getTok();
1957 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00001958 // Eat optional hash.
1959 if (parseOptionalToken(AsmToken::Hash) ||
1960 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001961 const MCExpr *ImmVal;
1962 if (getParser().parseExpression(ImmVal))
1963 return MatchOperand_ParseFail;
1964
1965 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1966 if (!MCE) {
1967 TokError("immediate value expected for prefetch operand");
1968 return MatchOperand_ParseFail;
1969 }
1970 unsigned prfop = MCE->getValue();
1971 if (prfop > 31) {
1972 TokError("prefetch operand out of range, [0,31] expected");
1973 return MatchOperand_ParseFail;
1974 }
1975
Tim Northovere6ae6762016-07-05 21:23:04 +00001976 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
1977 Operands.push_back(AArch64Operand::CreatePrefetch(
1978 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001979 return MatchOperand_Success;
1980 }
1981
1982 if (Tok.isNot(AsmToken::Identifier)) {
1983 TokError("pre-fetch hint expected");
1984 return MatchOperand_ParseFail;
1985 }
1986
Tim Northovere6ae6762016-07-05 21:23:04 +00001987 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
1988 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001989 TokError("pre-fetch hint expected");
1990 return MatchOperand_ParseFail;
1991 }
1992
1993 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00001994 Operands.push_back(AArch64Operand::CreatePrefetch(
1995 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001996 return MatchOperand_Success;
1997}
1998
Oliver Stannarda34e4702015-12-01 10:48:51 +00001999/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002000OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002001AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2002 MCAsmParser &Parser = getParser();
2003 SMLoc S = getLoc();
2004 const AsmToken &Tok = Parser.getTok();
2005 if (Tok.isNot(AsmToken::Identifier)) {
2006 TokError("invalid operand for instruction");
2007 return MatchOperand_ParseFail;
2008 }
2009
Tim Northovere6ae6762016-07-05 21:23:04 +00002010 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2011 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002012 TokError("invalid operand for instruction");
2013 return MatchOperand_ParseFail;
2014 }
2015
2016 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002017 Operands.push_back(AArch64Operand::CreatePSBHint(
2018 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002019 return MatchOperand_Success;
2020}
2021
Tim Northover3b0846e2014-05-24 12:50:23 +00002022/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2023/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002024OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002025AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002026 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002027 SMLoc S = getLoc();
2028 const MCExpr *Expr;
2029
2030 if (Parser.getTok().is(AsmToken::Hash)) {
2031 Parser.Lex(); // Eat hash token.
2032 }
2033
2034 if (parseSymbolicImmVal(Expr))
2035 return MatchOperand_ParseFail;
2036
2037 AArch64MCExpr::VariantKind ELFRefKind;
2038 MCSymbolRefExpr::VariantKind DarwinRefKind;
2039 int64_t Addend;
2040 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2041 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2042 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2043 // No modifier was specified at all; this is the syntax for an ELF basic
2044 // ADRP relocation (unfortunately).
2045 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002046 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002047 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2048 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2049 Addend != 0) {
2050 Error(S, "gotpage label reference not allowed an addend");
2051 return MatchOperand_ParseFail;
2052 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2053 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2054 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2055 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2056 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2057 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2058 // The operand must be an @page or @gotpage qualified symbolref.
2059 Error(S, "page or gotpage label reference expected");
2060 return MatchOperand_ParseFail;
2061 }
2062 }
2063
2064 // We have either a label reference possibly with addend or an immediate. The
2065 // addend is a raw value here. The linker will adjust it to only reference the
2066 // page.
2067 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2068 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2069
2070 return MatchOperand_Success;
2071}
2072
2073/// tryParseAdrLabel - Parse and validate a source label for the ADR
2074/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002075OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002076AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2077 SMLoc S = getLoc();
2078 const MCExpr *Expr;
2079
Nirav Davee833c6c2016-11-08 18:31:04 +00002080 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002081 if (getParser().parseExpression(Expr))
2082 return MatchOperand_ParseFail;
2083
2084 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2085 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2086
2087 return MatchOperand_Success;
2088}
2089
2090/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002091OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002092AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002093 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002094 SMLoc S = getLoc();
2095
Nirav Davee833c6c2016-11-08 18:31:04 +00002096 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002097
2098 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002099 bool isNegative = parseOptionalToken(AsmToken::Minus);
2100
Tim Northover3b0846e2014-05-24 12:50:23 +00002101 const AsmToken &Tok = Parser.getTok();
2102 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002103 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002104 if (isNegative)
2105 RealVal.changeSign();
2106
Tim Northover3b0846e2014-05-24 12:50:23 +00002107 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002108 int Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2109 Parser.Lex(); // Eat the token.
2110 // Check for out of range values. As an exception, we let Zero through,
2111 // as we handle that special case in post-processing before matching in
2112 // order to use the zero register for it.
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002113 if (Val == -1 && !RealVal.isPosZero()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002114 TokError("expected compatible register or floating-point constant");
2115 return MatchOperand_ParseFail;
2116 }
2117 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2118 return MatchOperand_Success;
2119 }
2120 if (Tok.is(AsmToken::Integer)) {
2121 int64_t Val;
2122 if (!isNegative && Tok.getString().startswith("0x")) {
2123 Val = Tok.getIntVal();
2124 if (Val > 255 || Val < 0) {
2125 TokError("encoded floating point value out of range");
2126 return MatchOperand_ParseFail;
2127 }
2128 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002129 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002130 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2131 // If we had a '-' in front, toggle the sign bit.
2132 IntVal ^= (uint64_t)isNegative << 63;
2133 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2134 }
2135 Parser.Lex(); // Eat the token.
2136 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2137 return MatchOperand_Success;
2138 }
2139
2140 if (!Hash)
2141 return MatchOperand_NoMatch;
2142
2143 TokError("invalid floating point immediate");
2144 return MatchOperand_ParseFail;
2145}
2146
2147/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002148OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002149AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002150 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002151 SMLoc S = getLoc();
2152
2153 if (Parser.getTok().is(AsmToken::Hash))
2154 Parser.Lex(); // Eat '#'
2155 else if (Parser.getTok().isNot(AsmToken::Integer))
2156 // Operand should start from # or should be integer, emit error otherwise.
2157 return MatchOperand_NoMatch;
2158
2159 const MCExpr *Imm;
2160 if (parseSymbolicImmVal(Imm))
2161 return MatchOperand_ParseFail;
2162 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2163 uint64_t ShiftAmount = 0;
2164 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2165 if (MCE) {
2166 int64_t Val = MCE->getValue();
2167 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002168 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002169 ShiftAmount = 12;
2170 }
2171 }
2172 SMLoc E = Parser.getTok().getLoc();
2173 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2174 getContext()));
2175 return MatchOperand_Success;
2176 }
2177
2178 // Eat ','
2179 Parser.Lex();
2180
2181 // The optional operand must be "lsl #N" where N is non-negative.
2182 if (!Parser.getTok().is(AsmToken::Identifier) ||
2183 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2184 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2185 return MatchOperand_ParseFail;
2186 }
2187
2188 // Eat 'lsl'
2189 Parser.Lex();
2190
Nirav Davee833c6c2016-11-08 18:31:04 +00002191 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002192
2193 if (Parser.getTok().isNot(AsmToken::Integer)) {
2194 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2195 return MatchOperand_ParseFail;
2196 }
2197
2198 int64_t ShiftAmount = Parser.getTok().getIntVal();
2199
2200 if (ShiftAmount < 0) {
2201 Error(Parser.getTok().getLoc(), "positive shift amount required");
2202 return MatchOperand_ParseFail;
2203 }
2204 Parser.Lex(); // Eat the number
2205
2206 SMLoc E = Parser.getTok().getLoc();
2207 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2208 S, E, getContext()));
2209 return MatchOperand_Success;
2210}
2211
2212/// parseCondCodeString - Parse a Condition Code string.
2213AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2214 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2215 .Case("eq", AArch64CC::EQ)
2216 .Case("ne", AArch64CC::NE)
2217 .Case("cs", AArch64CC::HS)
2218 .Case("hs", AArch64CC::HS)
2219 .Case("cc", AArch64CC::LO)
2220 .Case("lo", AArch64CC::LO)
2221 .Case("mi", AArch64CC::MI)
2222 .Case("pl", AArch64CC::PL)
2223 .Case("vs", AArch64CC::VS)
2224 .Case("vc", AArch64CC::VC)
2225 .Case("hi", AArch64CC::HI)
2226 .Case("ls", AArch64CC::LS)
2227 .Case("ge", AArch64CC::GE)
2228 .Case("lt", AArch64CC::LT)
2229 .Case("gt", AArch64CC::GT)
2230 .Case("le", AArch64CC::LE)
2231 .Case("al", AArch64CC::AL)
2232 .Case("nv", AArch64CC::NV)
2233 .Default(AArch64CC::Invalid);
2234 return CC;
2235}
2236
2237/// parseCondCode - Parse a Condition Code operand.
2238bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2239 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002240 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002241 SMLoc S = getLoc();
2242 const AsmToken &Tok = Parser.getTok();
2243 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2244
2245 StringRef Cond = Tok.getString();
2246 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2247 if (CC == AArch64CC::Invalid)
2248 return TokError("invalid condition code");
2249 Parser.Lex(); // Eat identifier token.
2250
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002251 if (invertCondCode) {
2252 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2253 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002254 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002255 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002256
2257 Operands.push_back(
2258 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2259 return false;
2260}
2261
2262/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2263/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002264OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002265AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002266 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002267 const AsmToken &Tok = Parser.getTok();
2268 std::string LowerID = Tok.getString().lower();
2269 AArch64_AM::ShiftExtendType ShOp =
2270 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2271 .Case("lsl", AArch64_AM::LSL)
2272 .Case("lsr", AArch64_AM::LSR)
2273 .Case("asr", AArch64_AM::ASR)
2274 .Case("ror", AArch64_AM::ROR)
2275 .Case("msl", AArch64_AM::MSL)
2276 .Case("uxtb", AArch64_AM::UXTB)
2277 .Case("uxth", AArch64_AM::UXTH)
2278 .Case("uxtw", AArch64_AM::UXTW)
2279 .Case("uxtx", AArch64_AM::UXTX)
2280 .Case("sxtb", AArch64_AM::SXTB)
2281 .Case("sxth", AArch64_AM::SXTH)
2282 .Case("sxtw", AArch64_AM::SXTW)
2283 .Case("sxtx", AArch64_AM::SXTX)
2284 .Default(AArch64_AM::InvalidShiftExtend);
2285
2286 if (ShOp == AArch64_AM::InvalidShiftExtend)
2287 return MatchOperand_NoMatch;
2288
2289 SMLoc S = Tok.getLoc();
2290 Parser.Lex();
2291
Nirav Davee833c6c2016-11-08 18:31:04 +00002292 bool Hash = parseOptionalToken(AsmToken::Hash);
2293
Tim Northover3b0846e2014-05-24 12:50:23 +00002294 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2295 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2296 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2297 ShOp == AArch64_AM::MSL) {
2298 // We expect a number here.
2299 TokError("expected #imm after shift specifier");
2300 return MatchOperand_ParseFail;
2301 }
2302
Chad Rosier2ff37b82016-12-27 16:58:09 +00002303 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002304 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2305 Operands.push_back(
2306 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2307 return MatchOperand_Success;
2308 }
2309
Chad Rosier2ff37b82016-12-27 16:58:09 +00002310 // Make sure we do actually have a number, identifier or a parenthesized
2311 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002312 SMLoc E = Parser.getTok().getLoc();
2313 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002314 !Parser.getTok().is(AsmToken::LParen) &&
2315 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002316 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002317 return MatchOperand_ParseFail;
2318 }
2319
2320 const MCExpr *ImmVal;
2321 if (getParser().parseExpression(ImmVal))
2322 return MatchOperand_ParseFail;
2323
2324 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2325 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002326 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002327 return MatchOperand_ParseFail;
2328 }
2329
Jim Grosbach57fd2622014-09-23 22:16:02 +00002330 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002331 Operands.push_back(AArch64Operand::CreateShiftExtend(
2332 ShOp, MCE->getValue(), true, S, E, getContext()));
2333 return MatchOperand_Success;
2334}
2335
2336/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2337/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2338bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2339 OperandVector &Operands) {
2340 if (Name.find('.') != StringRef::npos)
2341 return TokError("invalid operand");
2342
2343 Mnemonic = Name;
2344 Operands.push_back(
2345 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2346
Rafael Espindola961d4692014-11-11 05:18:41 +00002347 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002348 const AsmToken &Tok = Parser.getTok();
2349 StringRef Op = Tok.getString();
2350 SMLoc S = Tok.getLoc();
2351
2352 const MCExpr *Expr = nullptr;
2353
2354#define SYS_ALIAS(op1, Cn, Cm, op2) \
2355 do { \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002356 Expr = MCConstantExpr::create(op1, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002357 Operands.push_back( \
2358 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2359 Operands.push_back( \
2360 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext())); \
2361 Operands.push_back( \
2362 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext())); \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002363 Expr = MCConstantExpr::create(op2, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002364 Operands.push_back( \
2365 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
Eugene Zelenko049b0172017-01-06 00:30:53 +00002366 } while (false)
Tim Northover3b0846e2014-05-24 12:50:23 +00002367
2368 if (Mnemonic == "ic") {
2369 if (!Op.compare_lower("ialluis")) {
2370 // SYS #0, C7, C1, #0
2371 SYS_ALIAS(0, 7, 1, 0);
2372 } else if (!Op.compare_lower("iallu")) {
2373 // SYS #0, C7, C5, #0
2374 SYS_ALIAS(0, 7, 5, 0);
2375 } else if (!Op.compare_lower("ivau")) {
2376 // SYS #3, C7, C5, #1
2377 SYS_ALIAS(3, 7, 5, 1);
2378 } else {
2379 return TokError("invalid operand for IC instruction");
2380 }
2381 } else if (Mnemonic == "dc") {
2382 if (!Op.compare_lower("zva")) {
2383 // SYS #3, C7, C4, #1
2384 SYS_ALIAS(3, 7, 4, 1);
2385 } else if (!Op.compare_lower("ivac")) {
2386 // SYS #3, C7, C6, #1
2387 SYS_ALIAS(0, 7, 6, 1);
2388 } else if (!Op.compare_lower("isw")) {
2389 // SYS #0, C7, C6, #2
2390 SYS_ALIAS(0, 7, 6, 2);
2391 } else if (!Op.compare_lower("cvac")) {
2392 // SYS #3, C7, C10, #1
2393 SYS_ALIAS(3, 7, 10, 1);
2394 } else if (!Op.compare_lower("csw")) {
2395 // SYS #0, C7, C10, #2
2396 SYS_ALIAS(0, 7, 10, 2);
2397 } else if (!Op.compare_lower("cvau")) {
2398 // SYS #3, C7, C11, #1
2399 SYS_ALIAS(3, 7, 11, 1);
2400 } else if (!Op.compare_lower("civac")) {
2401 // SYS #3, C7, C14, #1
2402 SYS_ALIAS(3, 7, 14, 1);
2403 } else if (!Op.compare_lower("cisw")) {
2404 // SYS #0, C7, C14, #2
2405 SYS_ALIAS(0, 7, 14, 2);
Oliver Stannard1a81cc9f2015-11-26 15:28:47 +00002406 } else if (!Op.compare_lower("cvap")) {
2407 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2408 // SYS #3, C7, C12, #1
2409 SYS_ALIAS(3, 7, 12, 1);
2410 } else {
2411 return TokError("DC CVAP requires ARMv8.2a");
2412 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002413 } else {
2414 return TokError("invalid operand for DC instruction");
2415 }
2416 } else if (Mnemonic == "at") {
2417 if (!Op.compare_lower("s1e1r")) {
2418 // SYS #0, C7, C8, #0
2419 SYS_ALIAS(0, 7, 8, 0);
2420 } else if (!Op.compare_lower("s1e2r")) {
2421 // SYS #4, C7, C8, #0
2422 SYS_ALIAS(4, 7, 8, 0);
2423 } else if (!Op.compare_lower("s1e3r")) {
2424 // SYS #6, C7, C8, #0
2425 SYS_ALIAS(6, 7, 8, 0);
2426 } else if (!Op.compare_lower("s1e1w")) {
2427 // SYS #0, C7, C8, #1
2428 SYS_ALIAS(0, 7, 8, 1);
2429 } else if (!Op.compare_lower("s1e2w")) {
2430 // SYS #4, C7, C8, #1
2431 SYS_ALIAS(4, 7, 8, 1);
2432 } else if (!Op.compare_lower("s1e3w")) {
2433 // SYS #6, C7, C8, #1
2434 SYS_ALIAS(6, 7, 8, 1);
2435 } else if (!Op.compare_lower("s1e0r")) {
2436 // SYS #0, C7, C8, #3
2437 SYS_ALIAS(0, 7, 8, 2);
2438 } else if (!Op.compare_lower("s1e0w")) {
2439 // SYS #0, C7, C8, #3
2440 SYS_ALIAS(0, 7, 8, 3);
2441 } else if (!Op.compare_lower("s12e1r")) {
2442 // SYS #4, C7, C8, #4
2443 SYS_ALIAS(4, 7, 8, 4);
2444 } else if (!Op.compare_lower("s12e1w")) {
2445 // SYS #4, C7, C8, #5
2446 SYS_ALIAS(4, 7, 8, 5);
2447 } else if (!Op.compare_lower("s12e0r")) {
2448 // SYS #4, C7, C8, #6
2449 SYS_ALIAS(4, 7, 8, 6);
2450 } else if (!Op.compare_lower("s12e0w")) {
2451 // SYS #4, C7, C8, #7
2452 SYS_ALIAS(4, 7, 8, 7);
Oliver Stannard64c167d2015-11-26 15:34:44 +00002453 } else if (!Op.compare_lower("s1e1rp")) {
2454 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2455 // SYS #0, C7, C9, #0
2456 SYS_ALIAS(0, 7, 9, 0);
2457 } else {
2458 return TokError("AT S1E1RP requires ARMv8.2a");
2459 }
2460 } else if (!Op.compare_lower("s1e1wp")) {
2461 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2462 // SYS #0, C7, C9, #1
2463 SYS_ALIAS(0, 7, 9, 1);
2464 } else {
2465 return TokError("AT S1E1WP requires ARMv8.2a");
2466 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002467 } else {
2468 return TokError("invalid operand for AT instruction");
2469 }
2470 } else if (Mnemonic == "tlbi") {
2471 if (!Op.compare_lower("vmalle1is")) {
2472 // SYS #0, C8, C3, #0
2473 SYS_ALIAS(0, 8, 3, 0);
2474 } else if (!Op.compare_lower("alle2is")) {
2475 // SYS #4, C8, C3, #0
2476 SYS_ALIAS(4, 8, 3, 0);
2477 } else if (!Op.compare_lower("alle3is")) {
2478 // SYS #6, C8, C3, #0
2479 SYS_ALIAS(6, 8, 3, 0);
2480 } else if (!Op.compare_lower("vae1is")) {
2481 // SYS #0, C8, C3, #1
2482 SYS_ALIAS(0, 8, 3, 1);
2483 } else if (!Op.compare_lower("vae2is")) {
2484 // SYS #4, C8, C3, #1
2485 SYS_ALIAS(4, 8, 3, 1);
2486 } else if (!Op.compare_lower("vae3is")) {
2487 // SYS #6, C8, C3, #1
2488 SYS_ALIAS(6, 8, 3, 1);
2489 } else if (!Op.compare_lower("aside1is")) {
2490 // SYS #0, C8, C3, #2
2491 SYS_ALIAS(0, 8, 3, 2);
2492 } else if (!Op.compare_lower("vaae1is")) {
2493 // SYS #0, C8, C3, #3
2494 SYS_ALIAS(0, 8, 3, 3);
2495 } else if (!Op.compare_lower("alle1is")) {
2496 // SYS #4, C8, C3, #4
2497 SYS_ALIAS(4, 8, 3, 4);
2498 } else if (!Op.compare_lower("vale1is")) {
2499 // SYS #0, C8, C3, #5
2500 SYS_ALIAS(0, 8, 3, 5);
2501 } else if (!Op.compare_lower("vaale1is")) {
2502 // SYS #0, C8, C3, #7
2503 SYS_ALIAS(0, 8, 3, 7);
2504 } else if (!Op.compare_lower("vmalle1")) {
2505 // SYS #0, C8, C7, #0
2506 SYS_ALIAS(0, 8, 7, 0);
2507 } else if (!Op.compare_lower("alle2")) {
2508 // SYS #4, C8, C7, #0
2509 SYS_ALIAS(4, 8, 7, 0);
2510 } else if (!Op.compare_lower("vale2is")) {
2511 // SYS #4, C8, C3, #5
2512 SYS_ALIAS(4, 8, 3, 5);
2513 } else if (!Op.compare_lower("vale3is")) {
2514 // SYS #6, C8, C3, #5
2515 SYS_ALIAS(6, 8, 3, 5);
2516 } else if (!Op.compare_lower("alle3")) {
2517 // SYS #6, C8, C7, #0
2518 SYS_ALIAS(6, 8, 7, 0);
2519 } else if (!Op.compare_lower("vae1")) {
2520 // SYS #0, C8, C7, #1
2521 SYS_ALIAS(0, 8, 7, 1);
2522 } else if (!Op.compare_lower("vae2")) {
2523 // SYS #4, C8, C7, #1
2524 SYS_ALIAS(4, 8, 7, 1);
2525 } else if (!Op.compare_lower("vae3")) {
2526 // SYS #6, C8, C7, #1
2527 SYS_ALIAS(6, 8, 7, 1);
2528 } else if (!Op.compare_lower("aside1")) {
2529 // SYS #0, C8, C7, #2
2530 SYS_ALIAS(0, 8, 7, 2);
2531 } else if (!Op.compare_lower("vaae1")) {
2532 // SYS #0, C8, C7, #3
2533 SYS_ALIAS(0, 8, 7, 3);
2534 } else if (!Op.compare_lower("alle1")) {
2535 // SYS #4, C8, C7, #4
2536 SYS_ALIAS(4, 8, 7, 4);
2537 } else if (!Op.compare_lower("vale1")) {
2538 // SYS #0, C8, C7, #5
2539 SYS_ALIAS(0, 8, 7, 5);
2540 } else if (!Op.compare_lower("vale2")) {
2541 // SYS #4, C8, C7, #5
2542 SYS_ALIAS(4, 8, 7, 5);
2543 } else if (!Op.compare_lower("vale3")) {
2544 // SYS #6, C8, C7, #5
2545 SYS_ALIAS(6, 8, 7, 5);
2546 } else if (!Op.compare_lower("vaale1")) {
2547 // SYS #0, C8, C7, #7
2548 SYS_ALIAS(0, 8, 7, 7);
2549 } else if (!Op.compare_lower("ipas2e1")) {
2550 // SYS #4, C8, C4, #1
2551 SYS_ALIAS(4, 8, 4, 1);
2552 } else if (!Op.compare_lower("ipas2le1")) {
2553 // SYS #4, C8, C4, #5
2554 SYS_ALIAS(4, 8, 4, 5);
2555 } else if (!Op.compare_lower("ipas2e1is")) {
2556 // SYS #4, C8, C4, #1
2557 SYS_ALIAS(4, 8, 0, 1);
2558 } else if (!Op.compare_lower("ipas2le1is")) {
2559 // SYS #4, C8, C4, #5
2560 SYS_ALIAS(4, 8, 0, 5);
2561 } else if (!Op.compare_lower("vmalls12e1")) {
2562 // SYS #4, C8, C7, #6
2563 SYS_ALIAS(4, 8, 7, 6);
2564 } else if (!Op.compare_lower("vmalls12e1is")) {
2565 // SYS #4, C8, C3, #6
2566 SYS_ALIAS(4, 8, 3, 6);
2567 } else {
2568 return TokError("invalid operand for TLBI instruction");
2569 }
2570 }
2571
2572#undef SYS_ALIAS
2573
2574 Parser.Lex(); // Eat operand.
2575
2576 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2577 bool HasRegister = false;
2578
2579 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002580 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002581 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2582 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002583 HasRegister = true;
2584 }
2585
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 if (ExpectRegister && !HasRegister) {
2587 return TokError("specified " + Mnemonic + " op requires a register");
2588 }
2589 else if (!ExpectRegister && HasRegister) {
2590 return TokError("specified " + Mnemonic + " op does not use a register");
2591 }
2592
Nirav Davee833c6c2016-11-08 18:31:04 +00002593 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2594 return true;
2595
Tim Northover3b0846e2014-05-24 12:50:23 +00002596 return false;
2597}
2598
Alex Bradbury58eba092016-11-01 16:32:05 +00002599OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002600AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002601 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002602 const AsmToken &Tok = Parser.getTok();
2603
2604 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002605 if (parseOptionalToken(AsmToken::Hash) ||
2606 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002607 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002608 const MCExpr *ImmVal;
2609 SMLoc ExprLoc = getLoc();
2610 if (getParser().parseExpression(ImmVal))
2611 return MatchOperand_ParseFail;
2612 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2613 if (!MCE) {
2614 Error(ExprLoc, "immediate value expected for barrier operand");
2615 return MatchOperand_ParseFail;
2616 }
2617 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2618 Error(ExprLoc, "barrier operand out of range");
2619 return MatchOperand_ParseFail;
2620 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002621 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2622 Operands.push_back(AArch64Operand::CreateBarrier(
2623 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002624 return MatchOperand_Success;
2625 }
2626
2627 if (Tok.isNot(AsmToken::Identifier)) {
2628 TokError("invalid operand for instruction");
2629 return MatchOperand_ParseFail;
2630 }
2631
Tim Northovere6ae6762016-07-05 21:23:04 +00002632 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2633 if (!DB) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002634 TokError("invalid barrier option name");
2635 return MatchOperand_ParseFail;
2636 }
2637
2638 // The only valid named option for ISB is 'sy'
Tim Northovere6ae6762016-07-05 21:23:04 +00002639 if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002640 TokError("'sy' or #imm operand expected");
2641 return MatchOperand_ParseFail;
2642 }
2643
Tim Northovere6ae6762016-07-05 21:23:04 +00002644 Operands.push_back(AArch64Operand::CreateBarrier(
2645 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002646 Parser.Lex(); // Consume the option
2647
2648 return MatchOperand_Success;
2649}
2650
Alex Bradbury58eba092016-11-01 16:32:05 +00002651OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002652AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002653 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002654 const AsmToken &Tok = Parser.getTok();
2655
2656 if (Tok.isNot(AsmToken::Identifier))
2657 return MatchOperand_NoMatch;
2658
Tim Northovere6ae6762016-07-05 21:23:04 +00002659 int MRSReg, MSRReg;
2660 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2661 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2662 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2663 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2664 } else
2665 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002666
Tim Northovere6ae6762016-07-05 21:23:04 +00002667 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2668 unsigned PStateImm = -1;
2669 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2670 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002671
Tim Northovere6ae6762016-07-05 21:23:04 +00002672 Operands.push_back(
2673 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2674 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002675 Parser.Lex(); // Eat identifier
2676
2677 return MatchOperand_Success;
2678}
2679
2680/// tryParseVectorRegister - Parse a vector register operand.
2681bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002682 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002683 if (Parser.getTok().isNot(AsmToken::Identifier))
2684 return true;
2685
2686 SMLoc S = getLoc();
2687 // Check for a vector register specifier first.
2688 StringRef Kind;
2689 int64_t Reg = tryMatchVectorRegister(Kind, false);
2690 if (Reg == -1)
2691 return true;
2692 Operands.push_back(
2693 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2694 // If there was an explicit qualifier, that goes on as a literal text
2695 // operand.
2696 if (!Kind.empty())
2697 Operands.push_back(
2698 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2699
2700 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002701 SMLoc SIdx = getLoc();
2702 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002703 const MCExpr *ImmVal;
2704 if (getParser().parseExpression(ImmVal))
2705 return false;
2706 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2707 if (!MCE) {
2708 TokError("immediate value expected for vector index");
2709 return false;
2710 }
2711
2712 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002713
Nirav Davee833c6c2016-11-08 18:31:04 +00002714 if (parseToken(AsmToken::RBrac, "']' expected"))
2715 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002716
2717 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2718 E, getContext()));
2719 }
2720
2721 return false;
2722}
2723
2724/// parseRegister - Parse a non-vector register operand.
2725bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2726 SMLoc S = getLoc();
2727 // Try for a vector register.
2728 if (!tryParseVectorRegister(Operands))
2729 return false;
2730
2731 // Try for a scalar register.
2732 int64_t Reg = tryParseRegister();
2733 if (Reg == -1)
2734 return true;
2735 Operands.push_back(
2736 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2737
Tim Northover3b0846e2014-05-24 12:50:23 +00002738 return false;
2739}
2740
2741bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002742 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002743 bool HasELFModifier = false;
2744 AArch64MCExpr::VariantKind RefKind;
2745
Nirav Davee833c6c2016-11-08 18:31:04 +00002746 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002747 HasELFModifier = true;
2748
Nirav Davee833c6c2016-11-08 18:31:04 +00002749 if (Parser.getTok().isNot(AsmToken::Identifier))
2750 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002751
2752 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2753 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2754 .Case("lo12", AArch64MCExpr::VK_LO12)
2755 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2756 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2757 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2758 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2759 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2760 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2761 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2762 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2763 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2764 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2765 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2766 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2767 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2768 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2769 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2770 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2771 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2772 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2773 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2774 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2775 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2776 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2777 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2778 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2779 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2780 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2781 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2782 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2783 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2784 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2785 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2786 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2787 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2788 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2789 .Default(AArch64MCExpr::VK_INVALID);
2790
Nirav Davee833c6c2016-11-08 18:31:04 +00002791 if (RefKind == AArch64MCExpr::VK_INVALID)
2792 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002793
2794 Parser.Lex(); // Eat identifier
2795
Nirav Davee833c6c2016-11-08 18:31:04 +00002796 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002797 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002798 }
2799
2800 if (getParser().parseExpression(ImmVal))
2801 return true;
2802
2803 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002804 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002805
2806 return false;
2807}
2808
2809/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2810bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002811 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002812 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2813 SMLoc S = getLoc();
2814 Parser.Lex(); // Eat left bracket token.
2815 StringRef Kind;
2816 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2817 if (FirstReg == -1)
2818 return true;
2819 int64_t PrevReg = FirstReg;
2820 unsigned Count = 1;
2821
Nirav Davee833c6c2016-11-08 18:31:04 +00002822 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002823 SMLoc Loc = getLoc();
2824 StringRef NextKind;
2825 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2826 if (Reg == -1)
2827 return true;
2828 // Any Kind suffices must match on all regs in the list.
2829 if (Kind != NextKind)
2830 return Error(Loc, "mismatched register size suffix");
2831
2832 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2833
2834 if (Space == 0 || Space > 3) {
2835 return Error(Loc, "invalid number of vectors");
2836 }
2837
2838 Count += Space;
2839 }
2840 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002841 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002842 SMLoc Loc = getLoc();
2843 StringRef NextKind;
2844 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2845 if (Reg == -1)
2846 return true;
2847 // Any Kind suffices must match on all regs in the list.
2848 if (Kind != NextKind)
2849 return Error(Loc, "mismatched register size suffix");
2850
2851 // Registers must be incremental (with wraparound at 31)
2852 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2853 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2854 return Error(Loc, "registers must be sequential");
2855
2856 PrevReg = Reg;
2857 ++Count;
2858 }
2859 }
2860
Nirav Davee833c6c2016-11-08 18:31:04 +00002861 if (parseToken(AsmToken::RCurly, "'}' expected"))
2862 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002863
2864 if (Count > 4)
2865 return Error(S, "invalid number of vectors");
2866
2867 unsigned NumElements = 0;
2868 char ElementKind = 0;
2869 if (!Kind.empty())
2870 parseValidVectorKind(Kind, NumElements, ElementKind);
2871
2872 Operands.push_back(AArch64Operand::CreateVectorList(
2873 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2874
2875 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002876 SMLoc SIdx = getLoc();
2877 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002878 const MCExpr *ImmVal;
2879 if (getParser().parseExpression(ImmVal))
2880 return false;
2881 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2882 if (!MCE) {
2883 TokError("immediate value expected for vector index");
2884 return false;
2885 }
2886
2887 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002888 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002889 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002890
2891 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2892 E, getContext()));
2893 }
2894 return false;
2895}
2896
Alex Bradbury58eba092016-11-01 16:32:05 +00002897OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002898AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002899 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002900 const AsmToken &Tok = Parser.getTok();
2901 if (!Tok.is(AsmToken::Identifier))
2902 return MatchOperand_NoMatch;
2903
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002904 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00002905
2906 MCContext &Ctx = getContext();
2907 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2908 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2909 return MatchOperand_NoMatch;
2910
2911 SMLoc S = getLoc();
2912 Parser.Lex(); // Eat register
2913
Nirav Davee833c6c2016-11-08 18:31:04 +00002914 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002915 Operands.push_back(
2916 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2917 return MatchOperand_Success;
2918 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002919
Nirav Davee833c6c2016-11-08 18:31:04 +00002920 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002921
2922 if (Parser.getTok().isNot(AsmToken::Integer)) {
2923 Error(getLoc(), "index must be absent or #0");
2924 return MatchOperand_ParseFail;
2925 }
2926
2927 const MCExpr *ImmVal;
2928 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2929 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2930 Error(getLoc(), "index must be absent or #0");
2931 return MatchOperand_ParseFail;
2932 }
2933
2934 Operands.push_back(
2935 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2936 return MatchOperand_Success;
2937}
2938
2939/// parseOperand - Parse a arm instruction operand. For now this parses the
2940/// operand regardless of the mnemonic.
2941bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
2942 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002943 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002944 // Check if the current operand has a custom associated parser, if so, try to
2945 // custom parse the operand, or fallback to the general approach.
2946 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2947 if (ResTy == MatchOperand_Success)
2948 return false;
2949 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2950 // there was a match, but an error occurred, in which case, just return that
2951 // the operand parsing failed.
2952 if (ResTy == MatchOperand_ParseFail)
2953 return true;
2954
2955 // Nothing custom, so do general case parsing.
2956 SMLoc S, E;
2957 switch (getLexer().getKind()) {
2958 default: {
2959 SMLoc S = getLoc();
2960 const MCExpr *Expr;
2961 if (parseSymbolicImmVal(Expr))
2962 return Error(S, "invalid operand");
2963
2964 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2965 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2966 return false;
2967 }
2968 case AsmToken::LBrac: {
2969 SMLoc Loc = Parser.getTok().getLoc();
2970 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
2971 getContext()));
2972 Parser.Lex(); // Eat '['
2973
2974 // There's no comma after a '[', so we can parse the next operand
2975 // immediately.
2976 return parseOperand(Operands, false, false);
2977 }
2978 case AsmToken::LCurly:
2979 return parseVectorList(Operands);
2980 case AsmToken::Identifier: {
2981 // If we're expecting a Condition Code operand, then just parse that.
2982 if (isCondCode)
2983 return parseCondCode(Operands, invertCondCode);
2984
2985 // If it's a register name, parse it.
2986 if (!parseRegister(Operands))
2987 return false;
2988
2989 // This could be an optional "shift" or "extend" operand.
2990 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
2991 // We can only continue if no tokens were eaten.
2992 if (GotShift != MatchOperand_NoMatch)
2993 return GotShift;
2994
2995 // This was not a register so parse other operands that start with an
2996 // identifier (like labels) as expressions and create them as immediates.
2997 const MCExpr *IdVal;
2998 S = getLoc();
2999 if (getParser().parseExpression(IdVal))
3000 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003001 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3002 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3003 return false;
3004 }
3005 case AsmToken::Integer:
3006 case AsmToken::Real:
3007 case AsmToken::Hash: {
3008 // #42 -> immediate.
3009 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003010
3011 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003012
3013 // Parse a negative sign
3014 bool isNegative = false;
3015 if (Parser.getTok().is(AsmToken::Minus)) {
3016 isNegative = true;
3017 // We need to consume this token only when we have a Real, otherwise
3018 // we let parseSymbolicImmVal take care of it
3019 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3020 Parser.Lex();
3021 }
3022
3023 // The only Real that should come through here is a literal #0.0 for
3024 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3025 // so convert the value.
3026 const AsmToken &Tok = Parser.getTok();
3027 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003028 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003029 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3030 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3031 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3032 Mnemonic != "fcmlt")
3033 return TokError("unexpected floating point literal");
3034 else if (IntVal != 0 || isNegative)
3035 return TokError("expected floating-point constant #0.0");
3036 Parser.Lex(); // Eat the token.
3037
3038 Operands.push_back(
3039 AArch64Operand::CreateToken("#0", false, S, getContext()));
3040 Operands.push_back(
3041 AArch64Operand::CreateToken(".0", false, S, getContext()));
3042 return false;
3043 }
3044
3045 const MCExpr *ImmVal;
3046 if (parseSymbolicImmVal(ImmVal))
3047 return true;
3048
3049 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3050 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3051 return false;
3052 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003053 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003054 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003055 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003056 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003057 Parser.Lex(); // Eat '='
3058 const MCExpr *SubExprVal;
3059 if (getParser().parseExpression(SubExprVal))
3060 return true;
3061
David Peixottoae5ba762014-07-18 16:05:14 +00003062 if (Operands.size() < 2 ||
3063 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003064 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003065
3066 bool IsXReg =
3067 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3068 Operands[1]->getReg());
3069
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003070 MCContext& Ctx = getContext();
3071 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3072 // 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 +00003073 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003074 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3075 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3076 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3077 ShiftAmt += 16;
3078 Imm >>= 16;
3079 }
3080 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3081 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3082 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003083 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003084 if (ShiftAmt)
3085 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3086 ShiftAmt, true, S, E, Ctx));
3087 return false;
3088 }
David Peixottoae5ba762014-07-18 16:05:14 +00003089 APInt Simm = APInt(64, Imm << ShiftAmt);
3090 // check if the immediate is an unsigned or signed 32-bit int for W regs
3091 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3092 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003093 }
3094 // 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 +00003095 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003096 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003097 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3098 return false;
3099 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003100 }
3101}
3102
3103/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3104/// operands.
3105bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3106 StringRef Name, SMLoc NameLoc,
3107 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003108 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003109 Name = StringSwitch<StringRef>(Name.lower())
3110 .Case("beq", "b.eq")
3111 .Case("bne", "b.ne")
3112 .Case("bhs", "b.hs")
3113 .Case("bcs", "b.cs")
3114 .Case("blo", "b.lo")
3115 .Case("bcc", "b.cc")
3116 .Case("bmi", "b.mi")
3117 .Case("bpl", "b.pl")
3118 .Case("bvs", "b.vs")
3119 .Case("bvc", "b.vc")
3120 .Case("bhi", "b.hi")
3121 .Case("bls", "b.ls")
3122 .Case("bge", "b.ge")
3123 .Case("blt", "b.lt")
3124 .Case("bgt", "b.gt")
3125 .Case("ble", "b.le")
3126 .Case("bal", "b.al")
3127 .Case("bnv", "b.nv")
3128 .Default(Name);
3129
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003130 // First check for the AArch64-specific .req directive.
3131 if (Parser.getTok().is(AsmToken::Identifier) &&
3132 Parser.getTok().getIdentifier() == ".req") {
3133 parseDirectiveReq(Name, NameLoc);
3134 // We always return 'error' for this, as we're done with this
3135 // statement and don't need to match the 'instruction."
3136 return true;
3137 }
3138
Tim Northover3b0846e2014-05-24 12:50:23 +00003139 // Create the leading tokens for the mnemonic, split by '.' characters.
3140 size_t Start = 0, Next = Name.find('.');
3141 StringRef Head = Name.slice(Start, Next);
3142
3143 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003144 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3145 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003146
3147 Operands.push_back(
3148 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3149 Mnemonic = Head;
3150
3151 // Handle condition codes for a branch mnemonic
3152 if (Head == "b" && Next != StringRef::npos) {
3153 Start = Next;
3154 Next = Name.find('.', Start + 1);
3155 Head = Name.slice(Start + 1, Next);
3156
3157 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3158 (Head.data() - Name.data()));
3159 AArch64CC::CondCode CC = parseCondCodeString(Head);
3160 if (CC == AArch64CC::Invalid)
3161 return Error(SuffixLoc, "invalid condition code");
3162 Operands.push_back(
3163 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3164 Operands.push_back(
3165 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3166 }
3167
3168 // Add the remaining tokens in the mnemonic.
3169 while (Next != StringRef::npos) {
3170 Start = Next;
3171 Next = Name.find('.', Start + 1);
3172 Head = Name.slice(Start, Next);
3173 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3174 (Head.data() - Name.data()) + 1);
3175 Operands.push_back(
3176 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3177 }
3178
3179 // Conditional compare instructions have a Condition Code operand, which needs
3180 // to be parsed and an immediate operand created.
3181 bool condCodeFourthOperand =
3182 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3183 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3184 Head == "csinc" || Head == "csinv" || Head == "csneg");
3185
3186 // These instructions are aliases to some of the conditional select
3187 // instructions. However, the condition code is inverted in the aliased
3188 // instruction.
3189 //
3190 // FIXME: Is this the correct way to handle these? Or should the parser
3191 // generate the aliased instructions directly?
3192 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3193 bool condCodeThirdOperand =
3194 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3195
3196 // Read the remaining operands.
3197 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3198 // Read the first operand.
3199 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003200 return true;
3201 }
3202
3203 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003204 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003205 // Parse and remember the operand.
3206 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3207 (N == 3 && condCodeThirdOperand) ||
3208 (N == 2 && condCodeSecondOperand),
3209 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003210 return true;
3211 }
3212
3213 // After successfully parsing some operands there are two special cases to
3214 // consider (i.e. notional operands not separated by commas). Both are due
3215 // to memory specifiers:
3216 // + An RBrac will end an address for load/store/prefetch
3217 // + An '!' will indicate a pre-indexed operation.
3218 //
3219 // It's someone else's responsibility to make sure these tokens are sane
3220 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003221
Nirav Davee833c6c2016-11-08 18:31:04 +00003222 SMLoc RLoc = Parser.getTok().getLoc();
3223 if (parseOptionalToken(AsmToken::RBrac))
3224 Operands.push_back(
3225 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3226 SMLoc ELoc = Parser.getTok().getLoc();
3227 if (parseOptionalToken(AsmToken::Exclaim))
3228 Operands.push_back(
3229 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003230
3231 ++N;
3232 }
3233 }
3234
Nirav Davee833c6c2016-11-08 18:31:04 +00003235 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3236 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003237
Tim Northover3b0846e2014-05-24 12:50:23 +00003238 return false;
3239}
3240
3241// FIXME: This entire function is a giant hack to provide us with decent
3242// operand range validation/diagnostics until TableGen/MC can be extended
3243// to support autogeneration of this kind of validation.
3244bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3245 SmallVectorImpl<SMLoc> &Loc) {
3246 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3247 // Check for indexed addressing modes w/ the base register being the
3248 // same as a destination/source register or pair load where
3249 // the Rt == Rt2. All of those are undefined behaviour.
3250 switch (Inst.getOpcode()) {
3251 case AArch64::LDPSWpre:
3252 case AArch64::LDPWpost:
3253 case AArch64::LDPWpre:
3254 case AArch64::LDPXpost:
3255 case AArch64::LDPXpre: {
3256 unsigned Rt = Inst.getOperand(1).getReg();
3257 unsigned Rt2 = Inst.getOperand(2).getReg();
3258 unsigned Rn = Inst.getOperand(3).getReg();
3259 if (RI->isSubRegisterEq(Rn, Rt))
3260 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3261 "is also a destination");
3262 if (RI->isSubRegisterEq(Rn, Rt2))
3263 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3264 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003265 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003266 }
3267 case AArch64::LDPDi:
3268 case AArch64::LDPQi:
3269 case AArch64::LDPSi:
3270 case AArch64::LDPSWi:
3271 case AArch64::LDPWi:
3272 case AArch64::LDPXi: {
3273 unsigned Rt = Inst.getOperand(0).getReg();
3274 unsigned Rt2 = Inst.getOperand(1).getReg();
3275 if (Rt == Rt2)
3276 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3277 break;
3278 }
3279 case AArch64::LDPDpost:
3280 case AArch64::LDPDpre:
3281 case AArch64::LDPQpost:
3282 case AArch64::LDPQpre:
3283 case AArch64::LDPSpost:
3284 case AArch64::LDPSpre:
3285 case AArch64::LDPSWpost: {
3286 unsigned Rt = Inst.getOperand(1).getReg();
3287 unsigned Rt2 = Inst.getOperand(2).getReg();
3288 if (Rt == Rt2)
3289 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3290 break;
3291 }
3292 case AArch64::STPDpost:
3293 case AArch64::STPDpre:
3294 case AArch64::STPQpost:
3295 case AArch64::STPQpre:
3296 case AArch64::STPSpost:
3297 case AArch64::STPSpre:
3298 case AArch64::STPWpost:
3299 case AArch64::STPWpre:
3300 case AArch64::STPXpost:
3301 case AArch64::STPXpre: {
3302 unsigned Rt = Inst.getOperand(1).getReg();
3303 unsigned Rt2 = Inst.getOperand(2).getReg();
3304 unsigned Rn = Inst.getOperand(3).getReg();
3305 if (RI->isSubRegisterEq(Rn, Rt))
3306 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3307 "is also a source");
3308 if (RI->isSubRegisterEq(Rn, Rt2))
3309 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3310 "is also a source");
3311 break;
3312 }
3313 case AArch64::LDRBBpre:
3314 case AArch64::LDRBpre:
3315 case AArch64::LDRHHpre:
3316 case AArch64::LDRHpre:
3317 case AArch64::LDRSBWpre:
3318 case AArch64::LDRSBXpre:
3319 case AArch64::LDRSHWpre:
3320 case AArch64::LDRSHXpre:
3321 case AArch64::LDRSWpre:
3322 case AArch64::LDRWpre:
3323 case AArch64::LDRXpre:
3324 case AArch64::LDRBBpost:
3325 case AArch64::LDRBpost:
3326 case AArch64::LDRHHpost:
3327 case AArch64::LDRHpost:
3328 case AArch64::LDRSBWpost:
3329 case AArch64::LDRSBXpost:
3330 case AArch64::LDRSHWpost:
3331 case AArch64::LDRSHXpost:
3332 case AArch64::LDRSWpost:
3333 case AArch64::LDRWpost:
3334 case AArch64::LDRXpost: {
3335 unsigned Rt = Inst.getOperand(1).getReg();
3336 unsigned Rn = Inst.getOperand(2).getReg();
3337 if (RI->isSubRegisterEq(Rn, Rt))
3338 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3339 "is also a source");
3340 break;
3341 }
3342 case AArch64::STRBBpost:
3343 case AArch64::STRBpost:
3344 case AArch64::STRHHpost:
3345 case AArch64::STRHpost:
3346 case AArch64::STRWpost:
3347 case AArch64::STRXpost:
3348 case AArch64::STRBBpre:
3349 case AArch64::STRBpre:
3350 case AArch64::STRHHpre:
3351 case AArch64::STRHpre:
3352 case AArch64::STRWpre:
3353 case AArch64::STRXpre: {
3354 unsigned Rt = Inst.getOperand(1).getReg();
3355 unsigned Rn = Inst.getOperand(2).getReg();
3356 if (RI->isSubRegisterEq(Rn, Rt))
3357 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3358 "is also a source");
3359 break;
3360 }
3361 }
3362
3363 // Now check immediate ranges. Separate from the above as there is overlap
3364 // in the instructions being checked and this keeps the nested conditionals
3365 // to a minimum.
3366 switch (Inst.getOpcode()) {
3367 case AArch64::ADDSWri:
3368 case AArch64::ADDSXri:
3369 case AArch64::ADDWri:
3370 case AArch64::ADDXri:
3371 case AArch64::SUBSWri:
3372 case AArch64::SUBSXri:
3373 case AArch64::SUBWri:
3374 case AArch64::SUBXri: {
3375 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3376 // some slight duplication here.
3377 if (Inst.getOperand(2).isExpr()) {
3378 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3379 AArch64MCExpr::VariantKind ELFRefKind;
3380 MCSymbolRefExpr::VariantKind DarwinRefKind;
3381 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003382 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3383
3384 // Only allow these with ADDXri.
3385 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3386 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3387 Inst.getOpcode() == AArch64::ADDXri)
3388 return false;
3389
3390 // Only allow these with ADDXri/ADDWri
3391 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3392 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3393 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3394 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3395 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3396 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3397 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3398 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3399 (Inst.getOpcode() == AArch64::ADDXri ||
3400 Inst.getOpcode() == AArch64::ADDWri))
3401 return false;
3402
3403 // Don't allow symbol refs in the immediate field otherwise
3404 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3405 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3406 // 'cmp w0, 'borked')
3407 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003408 }
Diana Picusc93518d2016-10-11 09:17:47 +00003409 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003410 }
3411 return false;
3412 }
3413 default:
3414 return false;
3415 }
3416}
3417
3418bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3419 switch (ErrCode) {
3420 case Match_MissingFeature:
3421 return Error(Loc,
3422 "instruction requires a CPU feature not currently enabled");
3423 case Match_InvalidOperand:
3424 return Error(Loc, "invalid operand for instruction");
3425 case Match_InvalidSuffix:
3426 return Error(Loc, "invalid type suffix for instruction");
3427 case Match_InvalidCondCode:
3428 return Error(Loc, "expected AArch64 condition code");
3429 case Match_AddSubRegExtendSmall:
3430 return Error(Loc,
3431 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3432 case Match_AddSubRegExtendLarge:
3433 return Error(Loc,
3434 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3435 case Match_AddSubSecondSource:
3436 return Error(Loc,
3437 "expected compatible register, symbol or integer in range [0, 4095]");
3438 case Match_LogicalSecondSource:
3439 return Error(Loc, "expected compatible register or logical immediate");
3440 case Match_InvalidMovImm32Shift:
3441 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3442 case Match_InvalidMovImm64Shift:
3443 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3444 case Match_AddSubRegShift32:
3445 return Error(Loc,
3446 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3447 case Match_AddSubRegShift64:
3448 return Error(Loc,
3449 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3450 case Match_InvalidFPImm:
3451 return Error(Loc,
3452 "expected compatible register or floating-point constant");
3453 case Match_InvalidMemoryIndexedSImm9:
3454 return Error(Loc, "index must be an integer in range [-256, 255].");
3455 case Match_InvalidMemoryIndexed4SImm7:
3456 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3457 case Match_InvalidMemoryIndexed8SImm7:
3458 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3459 case Match_InvalidMemoryIndexed16SImm7:
3460 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3461 case Match_InvalidMemoryWExtend8:
3462 return Error(Loc,
3463 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3464 case Match_InvalidMemoryWExtend16:
3465 return Error(Loc,
3466 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3467 case Match_InvalidMemoryWExtend32:
3468 return Error(Loc,
3469 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3470 case Match_InvalidMemoryWExtend64:
3471 return Error(Loc,
3472 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3473 case Match_InvalidMemoryWExtend128:
3474 return Error(Loc,
3475 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3476 case Match_InvalidMemoryXExtend8:
3477 return Error(Loc,
3478 "expected 'lsl' or 'sxtx' with optional shift of #0");
3479 case Match_InvalidMemoryXExtend16:
3480 return Error(Loc,
3481 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3482 case Match_InvalidMemoryXExtend32:
3483 return Error(Loc,
3484 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3485 case Match_InvalidMemoryXExtend64:
3486 return Error(Loc,
3487 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3488 case Match_InvalidMemoryXExtend128:
3489 return Error(Loc,
3490 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3491 case Match_InvalidMemoryIndexed1:
3492 return Error(Loc, "index must be an integer in range [0, 4095].");
3493 case Match_InvalidMemoryIndexed2:
3494 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3495 case Match_InvalidMemoryIndexed4:
3496 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3497 case Match_InvalidMemoryIndexed8:
3498 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3499 case Match_InvalidMemoryIndexed16:
3500 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003501 case Match_InvalidImm0_1:
3502 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003503 case Match_InvalidImm0_7:
3504 return Error(Loc, "immediate must be an integer in range [0, 7].");
3505 case Match_InvalidImm0_15:
3506 return Error(Loc, "immediate must be an integer in range [0, 15].");
3507 case Match_InvalidImm0_31:
3508 return Error(Loc, "immediate must be an integer in range [0, 31].");
3509 case Match_InvalidImm0_63:
3510 return Error(Loc, "immediate must be an integer in range [0, 63].");
3511 case Match_InvalidImm0_127:
3512 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003513 case Match_InvalidImm0_255:
3514 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003515 case Match_InvalidImm0_65535:
3516 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3517 case Match_InvalidImm1_8:
3518 return Error(Loc, "immediate must be an integer in range [1, 8].");
3519 case Match_InvalidImm1_16:
3520 return Error(Loc, "immediate must be an integer in range [1, 16].");
3521 case Match_InvalidImm1_32:
3522 return Error(Loc, "immediate must be an integer in range [1, 32].");
3523 case Match_InvalidImm1_64:
3524 return Error(Loc, "immediate must be an integer in range [1, 64].");
3525 case Match_InvalidIndex1:
3526 return Error(Loc, "expected lane specifier '[1]'");
3527 case Match_InvalidIndexB:
3528 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3529 case Match_InvalidIndexH:
3530 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3531 case Match_InvalidIndexS:
3532 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3533 case Match_InvalidIndexD:
3534 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3535 case Match_InvalidLabel:
3536 return Error(Loc, "expected label or encodable integer pc offset");
3537 case Match_MRS:
3538 return Error(Loc, "expected readable system register");
3539 case Match_MSR:
3540 return Error(Loc, "expected writable system register or pstate");
3541 case Match_MnemonicFail:
3542 return Error(Loc, "unrecognized instruction mnemonic");
3543 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003544 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003545 }
3546}
3547
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003548static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003549
3550bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3551 OperandVector &Operands,
3552 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003553 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003554 bool MatchingInlineAsm) {
3555 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003556 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3557 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003558
David Blaikie960ea3f2014-06-08 16:18:35 +00003559 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003560 unsigned NumOperands = Operands.size();
3561
3562 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003563 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3564 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3565 if (Op2.isReg() && Op3.isImm()) {
3566 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003567 if (Op3CE) {
3568 uint64_t Op3Val = Op3CE->getValue();
3569 uint64_t NewOp3Val = 0;
3570 uint64_t NewOp4Val = 0;
3571 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003572 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003573 NewOp3Val = (32 - Op3Val) & 0x1f;
3574 NewOp4Val = 31 - Op3Val;
3575 } else {
3576 NewOp3Val = (64 - Op3Val) & 0x3f;
3577 NewOp4Val = 63 - Op3Val;
3578 }
3579
Jim Grosbach13760bd2015-05-30 01:25:56 +00003580 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3581 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003582
3583 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003584 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003585 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003586 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3587 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3588 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003589 }
3590 }
Tim Northover03b99f62015-04-30 18:28:58 +00003591 } else if (NumOperands == 4 && Tok == "bfc") {
3592 // FIXME: Horrible hack to handle BFC->BFM alias.
3593 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3594 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3595 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3596
3597 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3598 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3599 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3600
3601 if (LSBCE && WidthCE) {
3602 uint64_t LSB = LSBCE->getValue();
3603 uint64_t Width = WidthCE->getValue();
3604
3605 uint64_t RegWidth = 0;
3606 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3607 Op1.getReg()))
3608 RegWidth = 64;
3609 else
3610 RegWidth = 32;
3611
3612 if (LSB >= RegWidth)
3613 return Error(LSBOp.getStartLoc(),
3614 "expected integer in range [0, 31]");
3615 if (Width < 1 || Width > RegWidth)
3616 return Error(WidthOp.getStartLoc(),
3617 "expected integer in range [1, 32]");
3618
3619 uint64_t ImmR = 0;
3620 if (RegWidth == 32)
3621 ImmR = (32 - LSB) & 0x1f;
3622 else
3623 ImmR = (64 - LSB) & 0x3f;
3624
3625 uint64_t ImmS = Width - 1;
3626
3627 if (ImmR != 0 && ImmS >= ImmR)
3628 return Error(WidthOp.getStartLoc(),
3629 "requested insert overflows register");
3630
Jim Grosbach13760bd2015-05-30 01:25:56 +00003631 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3632 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003633 Operands[0] = AArch64Operand::CreateToken(
3634 "bfm", false, Op.getStartLoc(), getContext());
3635 Operands[2] = AArch64Operand::CreateReg(
3636 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3637 SMLoc(), getContext());
3638 Operands[3] = AArch64Operand::CreateImm(
3639 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3640 Operands.emplace_back(
3641 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3642 WidthOp.getEndLoc(), getContext()));
3643 }
3644 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003645 } else if (NumOperands == 5) {
3646 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3647 // UBFIZ -> UBFM aliases.
3648 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003649 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3650 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3651 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003652
David Blaikie960ea3f2014-06-08 16:18:35 +00003653 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3654 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3655 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003656
3657 if (Op3CE && Op4CE) {
3658 uint64_t Op3Val = Op3CE->getValue();
3659 uint64_t Op4Val = Op4CE->getValue();
3660
3661 uint64_t RegWidth = 0;
3662 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003663 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003664 RegWidth = 64;
3665 else
3666 RegWidth = 32;
3667
3668 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003669 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003670 "expected integer in range [0, 31]");
3671 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003672 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003673 "expected integer in range [1, 32]");
3674
3675 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003676 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003677 NewOp3Val = (32 - Op3Val) & 0x1f;
3678 else
3679 NewOp3Val = (64 - Op3Val) & 0x3f;
3680
3681 uint64_t NewOp4Val = Op4Val - 1;
3682
3683 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003684 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003685 "requested insert overflows register");
3686
3687 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003688 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003689 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003690 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003691 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003692 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003693 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003694 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003695 if (Tok == "bfi")
3696 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003697 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003698 else if (Tok == "sbfiz")
3699 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003700 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003701 else if (Tok == "ubfiz")
3702 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003703 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003704 else
3705 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003706 }
3707 }
3708
3709 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3710 // UBFX -> UBFM aliases.
3711 } else if (NumOperands == 5 &&
3712 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003713 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3714 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3715 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003716
David Blaikie960ea3f2014-06-08 16:18:35 +00003717 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3718 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3719 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003720
3721 if (Op3CE && Op4CE) {
3722 uint64_t Op3Val = Op3CE->getValue();
3723 uint64_t Op4Val = Op4CE->getValue();
3724
3725 uint64_t RegWidth = 0;
3726 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003727 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003728 RegWidth = 64;
3729 else
3730 RegWidth = 32;
3731
3732 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003733 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003734 "expected integer in range [0, 31]");
3735 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003736 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003737 "expected integer in range [1, 32]");
3738
3739 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3740
3741 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003742 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003743 "requested extract overflows register");
3744
3745 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003746 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003747 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003748 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003749 if (Tok == "bfxil")
3750 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003751 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003752 else if (Tok == "sbfx")
3753 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003754 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003755 else if (Tok == "ubfx")
3756 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003757 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003758 else
3759 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003760 }
3761 }
3762 }
3763 }
3764 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3765 // InstAlias can't quite handle this since the reg classes aren't
3766 // subclasses.
3767 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3768 // The source register can be Wn here, but the matcher expects a
3769 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003770 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3771 if (Op.isReg()) {
3772 unsigned Reg = getXRegFromWReg(Op.getReg());
3773 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3774 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003775 }
3776 }
3777 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3778 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003779 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3780 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003781 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003782 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003783 // The source register can be Wn here, but the matcher expects a
3784 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003785 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3786 if (Op.isReg()) {
3787 unsigned Reg = getXRegFromWReg(Op.getReg());
3788 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3789 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003790 }
3791 }
3792 }
3793 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3794 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003795 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3796 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003797 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003798 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003799 // The source register can be Wn here, but the matcher expects a
3800 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003801 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3802 if (Op.isReg()) {
3803 unsigned Reg = getWRegFromXReg(Op.getReg());
3804 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3805 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003806 }
3807 }
3808 }
3809
3810 // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
3811 if (NumOperands == 3 && Tok == "fmov") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003812 AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
3813 AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
3814 if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003815 unsigned zreg =
Oliver Stannardb25914e2015-11-27 13:04:48 +00003816 !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003817 RegOp.getReg())
Tim Northover3b0846e2014-05-24 12:50:23 +00003818 ? AArch64::WZR
3819 : AArch64::XZR;
David Blaikie960ea3f2014-06-08 16:18:35 +00003820 Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
3821 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003822 }
3823 }
3824
3825 MCInst Inst;
3826 // First try to match against the secondary set of tables containing the
3827 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3828 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003829 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003830
3831 // If that fails, try against the alternate table containing long-form NEON:
3832 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003833 if (MatchResult != Match_Success) {
3834 // But first, save the short-form match result: we can use it in case the
3835 // long-form match also fails.
3836 auto ShortFormNEONErrorInfo = ErrorInfo;
3837 auto ShortFormNEONMatchResult = MatchResult;
3838
Tim Northover3b0846e2014-05-24 12:50:23 +00003839 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003840 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003841
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003842 // Now, both matches failed, and the long-form match failed on the mnemonic
3843 // suffix token operand. The short-form match failure is probably more
3844 // relevant: use it instead.
3845 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003846 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003847 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3848 MatchResult = ShortFormNEONMatchResult;
3849 ErrorInfo = ShortFormNEONErrorInfo;
3850 }
3851 }
3852
Tim Northover3b0846e2014-05-24 12:50:23 +00003853 switch (MatchResult) {
3854 case Match_Success: {
3855 // Perform range checking and other semantic validations
3856 SmallVector<SMLoc, 8> OperandLocs;
3857 NumOperands = Operands.size();
3858 for (unsigned i = 1; i < NumOperands; ++i)
3859 OperandLocs.push_back(Operands[i]->getStartLoc());
3860 if (validateInstruction(Inst, OperandLocs))
3861 return true;
3862
3863 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003864 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003865 return false;
3866 }
3867 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003868 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003869 // Special case the error message for the very common case where only
3870 // a single subtarget feature is missing (neon, e.g.).
3871 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003872 uint64_t Mask = 1;
3873 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3874 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003875 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003876 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003877 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003878 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003879 }
3880 return Error(IDLoc, Msg);
3881 }
3882 case Match_MnemonicFail:
3883 return showMatchError(IDLoc, MatchResult);
3884 case Match_InvalidOperand: {
3885 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003886
Tim Northover26bb14e2014-08-18 11:49:42 +00003887 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003888 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003889 return Error(IDLoc, "too few operands for instruction",
3890 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003891
David Blaikie960ea3f2014-06-08 16:18:35 +00003892 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003893 if (ErrorLoc == SMLoc())
3894 ErrorLoc = IDLoc;
3895 }
3896 // If the match failed on a suffix token operand, tweak the diagnostic
3897 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003898 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
3899 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00003900 MatchResult = Match_InvalidSuffix;
3901
3902 return showMatchError(ErrorLoc, MatchResult);
3903 }
3904 case Match_InvalidMemoryIndexed1:
3905 case Match_InvalidMemoryIndexed2:
3906 case Match_InvalidMemoryIndexed4:
3907 case Match_InvalidMemoryIndexed8:
3908 case Match_InvalidMemoryIndexed16:
3909 case Match_InvalidCondCode:
3910 case Match_AddSubRegExtendSmall:
3911 case Match_AddSubRegExtendLarge:
3912 case Match_AddSubSecondSource:
3913 case Match_LogicalSecondSource:
3914 case Match_AddSubRegShift32:
3915 case Match_AddSubRegShift64:
3916 case Match_InvalidMovImm32Shift:
3917 case Match_InvalidMovImm64Shift:
3918 case Match_InvalidFPImm:
3919 case Match_InvalidMemoryWExtend8:
3920 case Match_InvalidMemoryWExtend16:
3921 case Match_InvalidMemoryWExtend32:
3922 case Match_InvalidMemoryWExtend64:
3923 case Match_InvalidMemoryWExtend128:
3924 case Match_InvalidMemoryXExtend8:
3925 case Match_InvalidMemoryXExtend16:
3926 case Match_InvalidMemoryXExtend32:
3927 case Match_InvalidMemoryXExtend64:
3928 case Match_InvalidMemoryXExtend128:
3929 case Match_InvalidMemoryIndexed4SImm7:
3930 case Match_InvalidMemoryIndexed8SImm7:
3931 case Match_InvalidMemoryIndexed16SImm7:
3932 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003933 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003934 case Match_InvalidImm0_7:
3935 case Match_InvalidImm0_15:
3936 case Match_InvalidImm0_31:
3937 case Match_InvalidImm0_63:
3938 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003939 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 case Match_InvalidImm0_65535:
3941 case Match_InvalidImm1_8:
3942 case Match_InvalidImm1_16:
3943 case Match_InvalidImm1_32:
3944 case Match_InvalidImm1_64:
3945 case Match_InvalidIndex1:
3946 case Match_InvalidIndexB:
3947 case Match_InvalidIndexH:
3948 case Match_InvalidIndexS:
3949 case Match_InvalidIndexD:
3950 case Match_InvalidLabel:
3951 case Match_MSR:
3952 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00003953 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003954 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003955 // Any time we get here, there's nothing fancy to do. Just get the
3956 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00003957 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003958 if (ErrorLoc == SMLoc())
3959 ErrorLoc = IDLoc;
3960 return showMatchError(ErrorLoc, MatchResult);
3961 }
3962 }
3963
3964 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003965}
3966
3967/// ParseDirective parses the arm specific directives
3968bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00003969 const MCObjectFileInfo::Environment Format =
3970 getContext().getObjectFileInfo()->getObjectFileType();
3971 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
3972 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00003973
Tim Northover3b0846e2014-05-24 12:50:23 +00003974 StringRef IDVal = DirectiveID.getIdentifier();
3975 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003976 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00003977 parseDirectiveArch(Loc);
3978 else if (IDVal == ".cpu")
3979 parseDirectiveCPU(Loc);
3980 else if (IDVal == ".hword")
3981 parseDirectiveWord(2, Loc);
3982 else if (IDVal == ".word")
3983 parseDirectiveWord(4, Loc);
3984 else if (IDVal == ".xword")
3985 parseDirectiveWord(8, Loc);
3986 else if (IDVal == ".tlsdesccall")
3987 parseDirectiveTLSDescCall(Loc);
3988 else if (IDVal == ".ltorg" || IDVal == ".pool")
3989 parseDirectiveLtorg(Loc);
3990 else if (IDVal == ".unreq")
3991 parseDirectiveUnreq(Loc);
3992 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00003993 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00003994 parseDirectiveInst(Loc);
3995 else
3996 return true;
3997 } else if (IDVal == MCLOHDirectiveName())
3998 parseDirectiveLOH(IDVal, Loc);
3999 else
4000 return true;
4001 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004002}
4003
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004004static const struct {
4005 const char *Name;
4006 const FeatureBitset Features;
4007} ExtensionMap[] = {
4008 { "crc", {AArch64::FeatureCRC} },
4009 { "crypto", {AArch64::FeatureCrypto} },
4010 { "fp", {AArch64::FeatureFPARMv8} },
4011 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004012 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004013 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004014
4015 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004016 { "pan", {} },
4017 { "lor", {} },
4018 { "rdma", {} },
4019 { "profile", {} },
4020};
4021
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004022/// parseDirectiveArch
4023/// ::= .arch token
4024bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4025 SMLoc ArchLoc = getLoc();
4026
4027 StringRef Arch, ExtensionString;
4028 std::tie(Arch, ExtensionString) =
4029 getParser().parseStringToEndOfStatement().trim().split('+');
4030
4031 unsigned ID = AArch64::parseArch(Arch);
Nirav Davee833c6c2016-11-08 18:31:04 +00004032 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
4033 return Error(ArchLoc, "unknown arch name");
4034
4035 if (parseToken(AsmToken::EndOfStatement))
4036 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004037
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004038 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004039 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004040 AArch64::getArchFeatures(ID, AArch64Features);
4041 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4042 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004043
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004044 MCSubtargetInfo &STI = copySTI();
4045 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4046 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4047
4048 SmallVector<StringRef, 4> RequestedExtensions;
4049 if (!ExtensionString.empty())
4050 ExtensionString.split(RequestedExtensions, '+');
4051
4052 FeatureBitset Features = STI.getFeatureBits();
4053 for (auto Name : RequestedExtensions) {
4054 bool EnableFeature = true;
4055
4056 if (Name.startswith_lower("no")) {
4057 EnableFeature = false;
4058 Name = Name.substr(2);
4059 }
4060
4061 for (const auto &Extension : ExtensionMap) {
4062 if (Extension.Name != Name)
4063 continue;
4064
4065 if (Extension.Features.none())
4066 report_fatal_error("unsupported architectural extension: " + Name);
4067
4068 FeatureBitset ToggleFeatures = EnableFeature
4069 ? (~Features & Extension.Features)
4070 : ( Features & Extension.Features);
4071 uint64_t Features =
4072 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4073 setAvailableFeatures(Features);
4074 break;
4075 }
4076 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004077 return false;
4078}
4079
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004080/// parseDirectiveCPU
4081/// ::= .cpu id
4082bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
4083 SMLoc CPULoc = getLoc();
4084
4085 StringRef CPU, ExtensionString;
4086 std::tie(CPU, ExtensionString) =
4087 getParser().parseStringToEndOfStatement().trim().split('+');
4088
Nirav Davee833c6c2016-11-08 18:31:04 +00004089 if (parseToken(AsmToken::EndOfStatement))
4090 return true;
4091
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004092 SmallVector<StringRef, 4> RequestedExtensions;
4093 if (!ExtensionString.empty())
4094 ExtensionString.split(RequestedExtensions, '+');
4095
4096 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4097 // once that is tablegen'ed
4098 if (!getSTI().isCPUStringValid(CPU)) {
4099 Error(CPULoc, "unknown CPU name");
4100 return false;
4101 }
4102
4103 MCSubtargetInfo &STI = copySTI();
4104 STI.setDefaultFeatures(CPU, "");
4105
4106 FeatureBitset Features = STI.getFeatureBits();
4107 for (auto Name : RequestedExtensions) {
4108 bool EnableFeature = true;
4109
4110 if (Name.startswith_lower("no")) {
4111 EnableFeature = false;
4112 Name = Name.substr(2);
4113 }
4114
4115 for (const auto &Extension : ExtensionMap) {
4116 if (Extension.Name != Name)
4117 continue;
4118
4119 if (Extension.Features.none())
4120 report_fatal_error("unsupported architectural extension: " + Name);
4121
4122 FeatureBitset ToggleFeatures = EnableFeature
4123 ? (~Features & Extension.Features)
4124 : ( Features & Extension.Features);
4125 uint64_t Features =
4126 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4127 setAvailableFeatures(Features);
4128
4129 break;
4130 }
4131 }
4132 return false;
4133}
4134
Tim Northover3b0846e2014-05-24 12:50:23 +00004135/// parseDirectiveWord
4136/// ::= .word [ expression (, expression)* ]
4137bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004138 auto parseOp = [&]() -> bool {
4139 const MCExpr *Value;
4140 if (getParser().parseExpression(Value))
4141 return true;
4142 getParser().getStreamer().EmitValue(Value, Size, L);
4143 return false;
4144 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004145
Nirav Davee833c6c2016-11-08 18:31:04 +00004146 if (parseMany(parseOp))
4147 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004148 return false;
4149}
4150
Chad Rosierdcd2a302014-10-22 20:35:57 +00004151/// parseDirectiveInst
4152/// ::= .inst opcode [, ...]
4153bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004154 if (getLexer().is(AsmToken::EndOfStatement))
4155 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004156
Nirav Davee833c6c2016-11-08 18:31:04 +00004157 auto parseOp = [&]() -> bool {
4158 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004159 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004160 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4161 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004162 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004163 if (check(!Value, L, "expected constant expression"))
4164 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004165 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004166 return false;
4167 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004168
Nirav Davee833c6c2016-11-08 18:31:04 +00004169 if (parseMany(parseOp))
4170 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004171 return false;
4172}
4173
Tim Northover3b0846e2014-05-24 12:50:23 +00004174// parseDirectiveTLSDescCall:
4175// ::= .tlsdesccall symbol
4176bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4177 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004178 if (check(getParser().parseIdentifier(Name), L,
4179 "expected symbol after directive") ||
4180 parseToken(AsmToken::EndOfStatement))
4181 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004182
Jim Grosbach6f482002015-05-18 18:43:14 +00004183 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004184 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4185 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004186
4187 MCInst Inst;
4188 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004189 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004190
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004191 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004192 return false;
4193}
4194
4195/// ::= .loh <lohName | lohId> label1, ..., labelN
4196/// The number of arguments depends on the loh identifier.
4197bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004198 MCLOHType Kind;
4199 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4200 if (getParser().getTok().isNot(AsmToken::Integer))
4201 return TokError("expected an identifier or a number in directive");
4202 // We successfully get a numeric value for the identifier.
4203 // Check if it is valid.
4204 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004205 if (Id <= -1U && !isValidMCLOHType(Id))
4206 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004207 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004208 } else {
4209 StringRef Name = getTok().getIdentifier();
4210 // We successfully parse an identifier.
4211 // Check if it is a recognized one.
4212 int Id = MCLOHNameToId(Name);
4213
4214 if (Id == -1)
4215 return TokError("invalid identifier in directive");
4216 Kind = (MCLOHType)Id;
4217 }
4218 // Consume the identifier.
4219 Lex();
4220 // Get the number of arguments of this LOH.
4221 int NbArgs = MCLOHIdToNbArgs(Kind);
4222
4223 assert(NbArgs != -1 && "Invalid number of arguments");
4224
4225 SmallVector<MCSymbol *, 3> Args;
4226 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4227 StringRef Name;
4228 if (getParser().parseIdentifier(Name))
4229 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004230 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004231
4232 if (Idx + 1 == NbArgs)
4233 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004234 if (parseToken(AsmToken::Comma,
4235 "unexpected token in '" + Twine(IDVal) + "' directive"))
4236 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004237 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004238 if (parseToken(AsmToken::EndOfStatement,
4239 "unexpected token in '" + Twine(IDVal) + "' directive"))
4240 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004241
4242 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4243 return false;
4244}
4245
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004246/// parseDirectiveLtorg
4247/// ::= .ltorg | .pool
4248bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004249 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4250 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004251 getTargetStreamer().emitCurrentConstantPool();
4252 return false;
4253}
4254
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004255/// parseDirectiveReq
4256/// ::= name .req registername
4257bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004258 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004259 Parser.Lex(); // Eat the '.req' token.
4260 SMLoc SRegLoc = getLoc();
4261 unsigned RegNum = tryParseRegister();
4262 bool IsVector = false;
4263
4264 if (RegNum == static_cast<unsigned>(-1)) {
4265 StringRef Kind;
4266 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004267 if (!Kind.empty())
4268 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004269 IsVector = true;
4270 }
4271
Nirav Dave2364748a2016-09-16 18:30:20 +00004272 if (RegNum == static_cast<unsigned>(-1))
4273 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004274
4275 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004276 if (parseToken(AsmToken::EndOfStatement,
4277 "unexpected input in .req directive"))
4278 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004279
4280 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004281 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004282 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4283
Nirav Dave2364748a2016-09-16 18:30:20 +00004284 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004285}
4286
4287/// parseDirectiveUneq
4288/// ::= .unreq registername
4289bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004290 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004291 if (getTok().isNot(AsmToken::Identifier))
4292 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004293 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4294 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004295 if (parseToken(AsmToken::EndOfStatement))
4296 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004297 return false;
4298}
4299
Tim Northover3b0846e2014-05-24 12:50:23 +00004300bool
4301AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4302 AArch64MCExpr::VariantKind &ELFRefKind,
4303 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4304 int64_t &Addend) {
4305 ELFRefKind = AArch64MCExpr::VK_INVALID;
4306 DarwinRefKind = MCSymbolRefExpr::VK_None;
4307 Addend = 0;
4308
4309 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4310 ELFRefKind = AE->getKind();
4311 Expr = AE->getSubExpr();
4312 }
4313
4314 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4315 if (SE) {
4316 // It's a simple symbol reference with no addend.
4317 DarwinRefKind = SE->getKind();
4318 return true;
4319 }
4320
4321 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4322 if (!BE)
4323 return false;
4324
4325 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4326 if (!SE)
4327 return false;
4328 DarwinRefKind = SE->getKind();
4329
4330 if (BE->getOpcode() != MCBinaryExpr::Add &&
4331 BE->getOpcode() != MCBinaryExpr::Sub)
4332 return false;
4333
4334 // See if the addend is is a constant, otherwise there's more going
4335 // on here than we can deal with.
4336 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4337 if (!AddendExpr)
4338 return false;
4339
4340 Addend = AddendExpr->getValue();
4341 if (BE->getOpcode() == MCBinaryExpr::Sub)
4342 Addend = -Addend;
4343
4344 // It's some symbol reference + a constant addend, but really
4345 // shouldn't use both Darwin and ELF syntax.
4346 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4347 DarwinRefKind == MCSymbolRefExpr::VK_None;
4348}
4349
4350/// Force static initialization.
4351extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004352 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4353 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4354 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004355}
4356
4357#define GET_REGISTER_MATCHER
4358#define GET_SUBTARGET_FEATURE_NAME
4359#define GET_MATCHER_IMPLEMENTATION
4360#include "AArch64GenAsmMatcher.inc"
4361
4362// Define this matcher function after the auto-generated include so we
4363// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004364unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004365 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004366 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004367 // If the kind is a token for a literal immediate, check if our asm
4368 // operand matches. This is for InstAliases which have a fixed-value
4369 // immediate in the syntax.
4370 int64_t ExpectedVal;
4371 switch (Kind) {
4372 default:
4373 return Match_InvalidOperand;
4374 case MCK__35_0:
4375 ExpectedVal = 0;
4376 break;
4377 case MCK__35_1:
4378 ExpectedVal = 1;
4379 break;
4380 case MCK__35_12:
4381 ExpectedVal = 12;
4382 break;
4383 case MCK__35_16:
4384 ExpectedVal = 16;
4385 break;
4386 case MCK__35_2:
4387 ExpectedVal = 2;
4388 break;
4389 case MCK__35_24:
4390 ExpectedVal = 24;
4391 break;
4392 case MCK__35_3:
4393 ExpectedVal = 3;
4394 break;
4395 case MCK__35_32:
4396 ExpectedVal = 32;
4397 break;
4398 case MCK__35_4:
4399 ExpectedVal = 4;
4400 break;
4401 case MCK__35_48:
4402 ExpectedVal = 48;
4403 break;
4404 case MCK__35_6:
4405 ExpectedVal = 6;
4406 break;
4407 case MCK__35_64:
4408 ExpectedVal = 64;
4409 break;
4410 case MCK__35_8:
4411 ExpectedVal = 8;
4412 break;
4413 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004414 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004415 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004416 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004417 if (!CE)
4418 return Match_InvalidOperand;
4419 if (CE->getValue() == ExpectedVal)
4420 return Match_Success;
4421 return Match_InvalidOperand;
4422}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004423
Alex Bradbury58eba092016-11-01 16:32:05 +00004424OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004425AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4426
4427 SMLoc S = getLoc();
4428
4429 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4430 Error(S, "expected register");
4431 return MatchOperand_ParseFail;
4432 }
4433
4434 int FirstReg = tryParseRegister();
4435 if (FirstReg == -1) {
4436 return MatchOperand_ParseFail;
4437 }
4438 const MCRegisterClass &WRegClass =
4439 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4440 const MCRegisterClass &XRegClass =
4441 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4442
4443 bool isXReg = XRegClass.contains(FirstReg),
4444 isWReg = WRegClass.contains(FirstReg);
4445 if (!isXReg && !isWReg) {
4446 Error(S, "expected first even register of a "
4447 "consecutive same-size even/odd register pair");
4448 return MatchOperand_ParseFail;
4449 }
4450
4451 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4452 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4453
4454 if (FirstEncoding & 0x1) {
4455 Error(S, "expected first even register of a "
4456 "consecutive same-size even/odd register pair");
4457 return MatchOperand_ParseFail;
4458 }
4459
4460 SMLoc M = getLoc();
4461 if (getParser().getTok().isNot(AsmToken::Comma)) {
4462 Error(M, "expected comma");
4463 return MatchOperand_ParseFail;
4464 }
4465 // Eat the comma
4466 getParser().Lex();
4467
4468 SMLoc E = getLoc();
4469 int SecondReg = tryParseRegister();
4470 if (SecondReg ==-1) {
4471 return MatchOperand_ParseFail;
4472 }
4473
Eugene Zelenko049b0172017-01-06 00:30:53 +00004474 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004475 (isXReg && !XRegClass.contains(SecondReg)) ||
4476 (isWReg && !WRegClass.contains(SecondReg))) {
4477 Error(E,"expected second odd register of a "
4478 "consecutive same-size even/odd register pair");
4479 return MatchOperand_ParseFail;
4480 }
Joel Jones504bf332016-10-24 13:37:13 +00004481
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004482 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004483 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004484 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4485 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4486 } else {
4487 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4488 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4489 }
4490
4491 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4492 getContext()));
4493
4494 return MatchOperand_Success;
4495}