blob: 36d3abbd44d69d49fd993ca6335094c94c8eeba1 [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"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000012#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000013#include "Utils/AArch64BaseInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000014#include "llvm/ADT/APInt.h"
15#include "llvm/ADT/STLExtras.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000017#include "llvm/ADT/StringExtras.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000018#include "llvm/ADT/StringSwitch.h"
19#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000020#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCExpr.h"
22#include "llvm/MC/MCInst.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000023#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000024#include "llvm/MC/MCParser/MCAsmLexer.h"
25#include "llvm/MC/MCParser/MCAsmParser.h"
26#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000027#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000028#include "llvm/MC/MCRegisterInfo.h"
29#include "llvm/MC/MCStreamer.h"
30#include "llvm/MC/MCSubtargetInfo.h"
31#include "llvm/MC/MCSymbol.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000032#include "llvm/Support/Debug.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/Support/ErrorHandling.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000034#include "llvm/Support/SourceMgr.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000035#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000036#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000037#include "llvm/Support/raw_ostream.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000038#include <cstdio>
39using namespace llvm;
40
41namespace {
42
43class AArch64Operand;
44
45class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000046private:
47 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000048
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000049 // Map of register aliases registers via the .req directive.
50 StringMap<std::pair<bool, unsigned> > RegisterReqs;
51
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000052 AArch64TargetStreamer &getTargetStreamer() {
53 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
54 return static_cast<AArch64TargetStreamer &>(TS);
55 }
56
Rafael Espindola961d4692014-11-11 05:18:41 +000057 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000058
59 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
60 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
61 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000062 unsigned matchRegisterNameAlias(StringRef Name, bool isVector);
Tim Northover3b0846e2014-05-24 12:50:23 +000063 int tryParseRegister();
64 int tryMatchVectorRegister(StringRef &Kind, bool expected);
65 bool parseRegister(OperandVector &Operands);
66 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
67 bool parseVectorList(OperandVector &Operands);
68 bool parseOperand(OperandVector &Operands, bool isCondCode,
69 bool invertCondCode);
70
Tim Northover3b0846e2014-05-24 12:50:23 +000071 bool showMatchError(SMLoc Loc, unsigned ErrCode);
72
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000073 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000074 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000075 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000076 bool parseDirectiveInst(SMLoc L);
77
Tim Northover3b0846e2014-05-24 12:50:23 +000078 bool parseDirectiveTLSDescCall(SMLoc L);
79
80 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000081 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000082
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000083 bool parseDirectiveReq(StringRef Name, SMLoc L);
84 bool parseDirectiveUnreq(SMLoc L);
85
Tim Northover3b0846e2014-05-24 12:50:23 +000086 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
87 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
88 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +000089 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +000090 bool MatchingInlineAsm) override;
91/// @name Auto-generated Match Functions
92/// {
93
94#define GET_ASSEMBLER_HEADER
95#include "AArch64GenAsmMatcher.inc"
96
97 /// }
98
99 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
100 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
101 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
102 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
103 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
104 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000105 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000106 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
107 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
108 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
109 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
110 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
111 bool tryParseVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000112 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000113
114public:
115 enum AArch64MatchResultTy {
116 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
117#define GET_OPERAND_DIAGNOSTIC_TYPES
118#include "AArch64GenAsmMatcher.inc"
119 };
Joel Jones504bf332016-10-24 13:37:13 +0000120 bool IsILP32;
Akira Hatanakab11ef082015-11-14 06:35:56 +0000121 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000122 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000123 : MCTargetAsmParser(Options, STI) {
Joel Jones504bf332016-10-24 13:37:13 +0000124 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000125 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000126 MCStreamer &S = getParser().getStreamer();
127 if (S.getTargetStreamer() == nullptr)
128 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000129
130 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000131 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000132 }
133
134 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
135 SMLoc NameLoc, OperandVector &Operands) override;
136 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
137 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000138 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000139 unsigned Kind) override;
140
141 static bool classifySymbolRef(const MCExpr *Expr,
142 AArch64MCExpr::VariantKind &ELFRefKind,
143 MCSymbolRefExpr::VariantKind &DarwinRefKind,
144 int64_t &Addend);
145};
146} // end anonymous namespace
147
148namespace {
149
150/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
151/// instruction.
152class AArch64Operand : public MCParsedAsmOperand {
153private:
154 enum KindTy {
155 k_Immediate,
156 k_ShiftedImm,
157 k_CondCode,
158 k_Register,
159 k_VectorList,
160 k_VectorIndex,
161 k_Token,
162 k_SysReg,
163 k_SysCR,
164 k_Prefetch,
165 k_ShiftExtend,
166 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000167 k_Barrier,
168 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000169 } Kind;
170
171 SMLoc StartLoc, EndLoc;
172
173 struct TokOp {
174 const char *Data;
175 unsigned Length;
176 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
177 };
178
179 struct RegOp {
180 unsigned RegNum;
181 bool isVector;
182 };
183
184 struct VectorListOp {
185 unsigned RegNum;
186 unsigned Count;
187 unsigned NumElements;
188 unsigned ElementKind;
189 };
190
191 struct VectorIndexOp {
192 unsigned Val;
193 };
194
195 struct ImmOp {
196 const MCExpr *Val;
197 };
198
199 struct ShiftedImmOp {
200 const MCExpr *Val;
201 unsigned ShiftAmount;
202 };
203
204 struct CondCodeOp {
205 AArch64CC::CondCode Code;
206 };
207
208 struct FPImmOp {
209 unsigned Val; // Encoded 8-bit representation.
210 };
211
212 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000213 const char *Data;
214 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000215 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000216 };
217
218 struct SysRegOp {
219 const char *Data;
220 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000221 uint32_t MRSReg;
222 uint32_t MSRReg;
223 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000224 };
225
226 struct SysCRImmOp {
227 unsigned Val;
228 };
229
230 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000231 const char *Data;
232 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000233 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000234 };
235
Oliver Stannarda34e4702015-12-01 10:48:51 +0000236 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000237 const char *Data;
238 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000239 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000240 };
241
Tim Northover3b0846e2014-05-24 12:50:23 +0000242 struct ShiftExtendOp {
243 AArch64_AM::ShiftExtendType Type;
244 unsigned Amount;
245 bool HasExplicitAmount;
246 };
247
248 struct ExtendOp {
249 unsigned Val;
250 };
251
252 union {
253 struct TokOp Tok;
254 struct RegOp Reg;
255 struct VectorListOp VectorList;
256 struct VectorIndexOp VectorIndex;
257 struct ImmOp Imm;
258 struct ShiftedImmOp ShiftedImm;
259 struct CondCodeOp CondCode;
260 struct FPImmOp FPImm;
261 struct BarrierOp Barrier;
262 struct SysRegOp SysReg;
263 struct SysCRImmOp SysCRImm;
264 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000265 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000266 struct ShiftExtendOp ShiftExtend;
267 };
268
269 // Keep the MCContext around as the MCExprs may need manipulated during
270 // the add<>Operands() calls.
271 MCContext &Ctx;
272
David Blaikie960ea3f2014-06-08 16:18:35 +0000273public:
David Blaikie9f380a32015-03-16 18:06:57 +0000274 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000275
Tim Northover3b0846e2014-05-24 12:50:23 +0000276 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
277 Kind = o.Kind;
278 StartLoc = o.StartLoc;
279 EndLoc = o.EndLoc;
280 switch (Kind) {
281 case k_Token:
282 Tok = o.Tok;
283 break;
284 case k_Immediate:
285 Imm = o.Imm;
286 break;
287 case k_ShiftedImm:
288 ShiftedImm = o.ShiftedImm;
289 break;
290 case k_CondCode:
291 CondCode = o.CondCode;
292 break;
293 case k_FPImm:
294 FPImm = o.FPImm;
295 break;
296 case k_Barrier:
297 Barrier = o.Barrier;
298 break;
299 case k_Register:
300 Reg = o.Reg;
301 break;
302 case k_VectorList:
303 VectorList = o.VectorList;
304 break;
305 case k_VectorIndex:
306 VectorIndex = o.VectorIndex;
307 break;
308 case k_SysReg:
309 SysReg = o.SysReg;
310 break;
311 case k_SysCR:
312 SysCRImm = o.SysCRImm;
313 break;
314 case k_Prefetch:
315 Prefetch = o.Prefetch;
316 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000317 case k_PSBHint:
318 PSBHint = o.PSBHint;
319 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000320 case k_ShiftExtend:
321 ShiftExtend = o.ShiftExtend;
322 break;
323 }
324 }
325
326 /// getStartLoc - Get the location of the first token of this operand.
327 SMLoc getStartLoc() const override { return StartLoc; }
328 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000329 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000330
331 StringRef getToken() const {
332 assert(Kind == k_Token && "Invalid access!");
333 return StringRef(Tok.Data, Tok.Length);
334 }
335
336 bool isTokenSuffix() const {
337 assert(Kind == k_Token && "Invalid access!");
338 return Tok.IsSuffix;
339 }
340
341 const MCExpr *getImm() const {
342 assert(Kind == k_Immediate && "Invalid access!");
343 return Imm.Val;
344 }
345
346 const MCExpr *getShiftedImmVal() const {
347 assert(Kind == k_ShiftedImm && "Invalid access!");
348 return ShiftedImm.Val;
349 }
350
351 unsigned getShiftedImmShift() const {
352 assert(Kind == k_ShiftedImm && "Invalid access!");
353 return ShiftedImm.ShiftAmount;
354 }
355
356 AArch64CC::CondCode getCondCode() const {
357 assert(Kind == k_CondCode && "Invalid access!");
358 return CondCode.Code;
359 }
360
361 unsigned getFPImm() const {
362 assert(Kind == k_FPImm && "Invalid access!");
363 return FPImm.Val;
364 }
365
366 unsigned getBarrier() const {
367 assert(Kind == k_Barrier && "Invalid access!");
368 return Barrier.Val;
369 }
370
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000371 StringRef getBarrierName() const {
372 assert(Kind == k_Barrier && "Invalid access!");
373 return StringRef(Barrier.Data, Barrier.Length);
374 }
375
Tim Northover3b0846e2014-05-24 12:50:23 +0000376 unsigned getReg() const override {
377 assert(Kind == k_Register && "Invalid access!");
378 return Reg.RegNum;
379 }
380
381 unsigned getVectorListStart() const {
382 assert(Kind == k_VectorList && "Invalid access!");
383 return VectorList.RegNum;
384 }
385
386 unsigned getVectorListCount() const {
387 assert(Kind == k_VectorList && "Invalid access!");
388 return VectorList.Count;
389 }
390
391 unsigned getVectorIndex() const {
392 assert(Kind == k_VectorIndex && "Invalid access!");
393 return VectorIndex.Val;
394 }
395
396 StringRef getSysReg() const {
397 assert(Kind == k_SysReg && "Invalid access!");
398 return StringRef(SysReg.Data, SysReg.Length);
399 }
400
Tim Northover3b0846e2014-05-24 12:50:23 +0000401 unsigned getSysCR() const {
402 assert(Kind == k_SysCR && "Invalid access!");
403 return SysCRImm.Val;
404 }
405
406 unsigned getPrefetch() const {
407 assert(Kind == k_Prefetch && "Invalid access!");
408 return Prefetch.Val;
409 }
410
Oliver Stannarda34e4702015-12-01 10:48:51 +0000411 unsigned getPSBHint() const {
412 assert(Kind == k_PSBHint && "Invalid access!");
413 return PSBHint.Val;
414 }
415
416 StringRef getPSBHintName() const {
417 assert(Kind == k_PSBHint && "Invalid access!");
418 return StringRef(PSBHint.Data, PSBHint.Length);
419 }
420
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000421 StringRef getPrefetchName() const {
422 assert(Kind == k_Prefetch && "Invalid access!");
423 return StringRef(Prefetch.Data, Prefetch.Length);
424 }
425
Tim Northover3b0846e2014-05-24 12:50:23 +0000426 AArch64_AM::ShiftExtendType getShiftExtendType() const {
427 assert(Kind == k_ShiftExtend && "Invalid access!");
428 return ShiftExtend.Type;
429 }
430
431 unsigned getShiftExtendAmount() const {
432 assert(Kind == k_ShiftExtend && "Invalid access!");
433 return ShiftExtend.Amount;
434 }
435
436 bool hasShiftExtendAmount() const {
437 assert(Kind == k_ShiftExtend && "Invalid access!");
438 return ShiftExtend.HasExplicitAmount;
439 }
440
441 bool isImm() const override { return Kind == k_Immediate; }
442 bool isMem() const override { return false; }
443 bool isSImm9() const {
444 if (!isImm())
445 return false;
446 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
447 if (!MCE)
448 return false;
449 int64_t Val = MCE->getValue();
450 return (Val >= -256 && Val < 256);
451 }
452 bool isSImm7s4() const {
453 if (!isImm())
454 return false;
455 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
456 if (!MCE)
457 return false;
458 int64_t Val = MCE->getValue();
459 return (Val >= -256 && Val <= 252 && (Val & 3) == 0);
460 }
461 bool isSImm7s8() const {
462 if (!isImm())
463 return false;
464 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
465 if (!MCE)
466 return false;
467 int64_t Val = MCE->getValue();
468 return (Val >= -512 && Val <= 504 && (Val & 7) == 0);
469 }
470 bool isSImm7s16() const {
471 if (!isImm())
472 return false;
473 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
474 if (!MCE)
475 return false;
476 int64_t Val = MCE->getValue();
477 return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
478 }
479
480 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
481 AArch64MCExpr::VariantKind ELFRefKind;
482 MCSymbolRefExpr::VariantKind DarwinRefKind;
483 int64_t Addend;
484 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
485 Addend)) {
486 // If we don't understand the expression, assume the best and
487 // let the fixup and relocation code deal with it.
488 return true;
489 }
490
491 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
492 ELFRefKind == AArch64MCExpr::VK_LO12 ||
493 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
494 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
495 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
496 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
497 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
498 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
499 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
500 // Note that we don't range-check the addend. It's adjusted modulo page
501 // size when converted, so there is no "out of range" condition when using
502 // @pageoff.
503 return Addend >= 0 && (Addend % Scale) == 0;
504 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
505 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
506 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
507 return Addend == 0;
508 }
509
510 return false;
511 }
512
513 template <int Scale> bool isUImm12Offset() const {
514 if (!isImm())
515 return false;
516
517 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
518 if (!MCE)
519 return isSymbolicUImm12Offset(getImm(), Scale);
520
521 int64_t Val = MCE->getValue();
522 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
523 }
524
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000525 bool isImm0_1() const {
526 if (!isImm())
527 return false;
528 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
529 if (!MCE)
530 return false;
531 int64_t Val = MCE->getValue();
532 return (Val >= 0 && Val < 2);
533 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000534 bool isImm0_7() const {
535 if (!isImm())
536 return false;
537 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
538 if (!MCE)
539 return false;
540 int64_t Val = MCE->getValue();
541 return (Val >= 0 && Val < 8);
542 }
543 bool isImm1_8() const {
544 if (!isImm())
545 return false;
546 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
547 if (!MCE)
548 return false;
549 int64_t Val = MCE->getValue();
550 return (Val > 0 && Val < 9);
551 }
552 bool isImm0_15() const {
553 if (!isImm())
554 return false;
555 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
556 if (!MCE)
557 return false;
558 int64_t Val = MCE->getValue();
559 return (Val >= 0 && Val < 16);
560 }
561 bool isImm1_16() const {
562 if (!isImm())
563 return false;
564 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
565 if (!MCE)
566 return false;
567 int64_t Val = MCE->getValue();
568 return (Val > 0 && Val < 17);
569 }
570 bool isImm0_31() const {
571 if (!isImm())
572 return false;
573 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
574 if (!MCE)
575 return false;
576 int64_t Val = MCE->getValue();
577 return (Val >= 0 && Val < 32);
578 }
579 bool isImm1_31() const {
580 if (!isImm())
581 return false;
582 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
583 if (!MCE)
584 return false;
585 int64_t Val = MCE->getValue();
586 return (Val >= 1 && Val < 32);
587 }
588 bool isImm1_32() const {
589 if (!isImm())
590 return false;
591 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
592 if (!MCE)
593 return false;
594 int64_t Val = MCE->getValue();
595 return (Val >= 1 && Val < 33);
596 }
597 bool isImm0_63() const {
598 if (!isImm())
599 return false;
600 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
601 if (!MCE)
602 return false;
603 int64_t Val = MCE->getValue();
604 return (Val >= 0 && Val < 64);
605 }
606 bool isImm1_63() const {
607 if (!isImm())
608 return false;
609 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
610 if (!MCE)
611 return false;
612 int64_t Val = MCE->getValue();
613 return (Val >= 1 && Val < 64);
614 }
615 bool isImm1_64() const {
616 if (!isImm())
617 return false;
618 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
619 if (!MCE)
620 return false;
621 int64_t Val = MCE->getValue();
622 return (Val >= 1 && Val < 65);
623 }
624 bool isImm0_127() const {
625 if (!isImm())
626 return false;
627 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
628 if (!MCE)
629 return false;
630 int64_t Val = MCE->getValue();
631 return (Val >= 0 && Val < 128);
632 }
633 bool isImm0_255() const {
634 if (!isImm())
635 return false;
636 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
637 if (!MCE)
638 return false;
639 int64_t Val = MCE->getValue();
640 return (Val >= 0 && Val < 256);
641 }
642 bool isImm0_65535() const {
643 if (!isImm())
644 return false;
645 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
646 if (!MCE)
647 return false;
648 int64_t Val = MCE->getValue();
649 return (Val >= 0 && Val < 65536);
650 }
651 bool isImm32_63() const {
652 if (!isImm())
653 return false;
654 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
655 if (!MCE)
656 return false;
657 int64_t Val = MCE->getValue();
658 return (Val >= 32 && Val < 64);
659 }
660 bool isLogicalImm32() const {
661 if (!isImm())
662 return false;
663 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
664 if (!MCE)
665 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000666 int64_t Val = MCE->getValue();
667 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
668 return false;
669 Val &= 0xFFFFFFFF;
670 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000671 }
672 bool isLogicalImm64() const {
673 if (!isImm())
674 return false;
675 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
676 if (!MCE)
677 return false;
678 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
679 }
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000680 bool isLogicalImm32Not() const {
681 if (!isImm())
682 return false;
683 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
684 if (!MCE)
685 return false;
686 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
687 return AArch64_AM::isLogicalImmediate(Val, 32);
688 }
689 bool isLogicalImm64Not() const {
690 if (!isImm())
691 return false;
692 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
693 if (!MCE)
694 return false;
695 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
696 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000697 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
698 bool isAddSubImm() const {
699 if (!isShiftedImm() && !isImm())
700 return false;
701
702 const MCExpr *Expr;
703
704 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
705 if (isShiftedImm()) {
706 unsigned Shift = ShiftedImm.ShiftAmount;
707 Expr = ShiftedImm.Val;
708 if (Shift != 0 && Shift != 12)
709 return false;
710 } else {
711 Expr = getImm();
712 }
713
714 AArch64MCExpr::VariantKind ELFRefKind;
715 MCSymbolRefExpr::VariantKind DarwinRefKind;
716 int64_t Addend;
717 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
718 DarwinRefKind, Addend)) {
719 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
720 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
721 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
722 || ELFRefKind == AArch64MCExpr::VK_LO12
723 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
724 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
725 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
726 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
727 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
728 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
729 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
730 }
731
Diana Picusc93518d2016-10-11 09:17:47 +0000732 // If it's a constant, it should be a real immediate in range:
733 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
734 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
735
736 // If it's an expression, we hope for the best and let the fixup/relocation
737 // code deal with it.
738 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000739 }
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000740 bool isAddSubImmNeg() const {
741 if (!isShiftedImm() && !isImm())
742 return false;
743
744 const MCExpr *Expr;
745
746 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
747 if (isShiftedImm()) {
748 unsigned Shift = ShiftedImm.ShiftAmount;
749 Expr = ShiftedImm.Val;
750 if (Shift != 0 && Shift != 12)
751 return false;
752 } else
753 Expr = getImm();
754
755 // Otherwise it should be a real negative immediate in range:
756 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
757 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
758 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000759 bool isCondCode() const { return Kind == k_CondCode; }
760 bool isSIMDImmType10() const {
761 if (!isImm())
762 return false;
763 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
764 if (!MCE)
765 return false;
766 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
767 }
768 bool isBranchTarget26() const {
769 if (!isImm())
770 return false;
771 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
772 if (!MCE)
773 return true;
774 int64_t Val = MCE->getValue();
775 if (Val & 0x3)
776 return false;
777 return (Val >= -(0x2000000 << 2) && Val <= (0x1ffffff << 2));
778 }
779 bool isPCRelLabel19() const {
780 if (!isImm())
781 return false;
782 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
783 if (!MCE)
784 return true;
785 int64_t Val = MCE->getValue();
786 if (Val & 0x3)
787 return false;
788 return (Val >= -(0x40000 << 2) && Val <= (0x3ffff << 2));
789 }
790 bool isBranchTarget14() const {
791 if (!isImm())
792 return false;
793 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
794 if (!MCE)
795 return true;
796 int64_t Val = MCE->getValue();
797 if (Val & 0x3)
798 return false;
799 return (Val >= -(0x2000 << 2) && Val <= (0x1fff << 2));
800 }
801
802 bool
803 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
804 if (!isImm())
805 return false;
806
807 AArch64MCExpr::VariantKind ELFRefKind;
808 MCSymbolRefExpr::VariantKind DarwinRefKind;
809 int64_t Addend;
810 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
811 DarwinRefKind, Addend)) {
812 return false;
813 }
814 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
815 return false;
816
817 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
818 if (ELFRefKind == AllowedModifiers[i])
819 return Addend == 0;
820 }
821
822 return false;
823 }
824
825 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000826 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000827 }
828
829 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000830 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
831 AArch64MCExpr::VK_TPREL_G2,
832 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000833 }
834
835 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000836 return isMovWSymbol({
837 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000838 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
839 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000840 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000841 }
842
843 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000844 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
845 AArch64MCExpr::VK_TPREL_G0,
846 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000847 }
848
849 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000850 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000851 }
852
853 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000854 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000855 }
856
857 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000858 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
859 AArch64MCExpr::VK_TPREL_G1_NC,
860 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000861 }
862
863 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000864 return isMovWSymbol(
865 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
866 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000867 }
868
869 template<int RegWidth, int Shift>
870 bool isMOVZMovAlias() const {
871 if (!isImm()) return false;
872
873 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
874 if (!CE) return false;
875 uint64_t Value = CE->getValue();
876
Tim Northoverdaa1c012016-06-16 01:42:25 +0000877 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000878 }
879
880 template<int RegWidth, int Shift>
881 bool isMOVNMovAlias() const {
882 if (!isImm()) return false;
883
884 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
885 if (!CE) return false;
886 uint64_t Value = CE->getValue();
887
Tim Northoverdaa1c012016-06-16 01:42:25 +0000888 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000889 }
890
891 bool isFPImm() const { return Kind == k_FPImm; }
892 bool isBarrier() const { return Kind == k_Barrier; }
893 bool isSysReg() const { return Kind == k_SysReg; }
894 bool isMRSSystemRegister() const {
895 if (!isSysReg()) return false;
896
Tim Northover7cd58932015-01-22 17:23:04 +0000897 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000898 }
899 bool isMSRSystemRegister() const {
900 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000901 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000902 }
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000903 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000904 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000905 return (SysReg.PStateField == AArch64PState::PAN ||
906 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000907 }
908 bool isSystemPStateFieldWithImm0_15() const {
909 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000910 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000911 }
912 bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
913 bool isVectorReg() const { return Kind == k_Register && Reg.isVector; }
914 bool isVectorRegLo() const {
915 return Kind == k_Register && Reg.isVector &&
916 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
917 Reg.RegNum);
918 }
919 bool isGPR32as64() const {
920 return Kind == k_Register && !Reg.isVector &&
921 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
922 }
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000923 bool isWSeqPair() const {
924 return Kind == k_Register && !Reg.isVector &&
925 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
926 Reg.RegNum);
927 }
928 bool isXSeqPair() const {
929 return Kind == k_Register && !Reg.isVector &&
930 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
931 Reg.RegNum);
932 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000933
934 bool isGPR64sp0() const {
935 return Kind == k_Register && !Reg.isVector &&
936 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
937 }
938
939 /// Is this a vector list with the type implicit (presumably attached to the
940 /// instruction itself)?
941 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
942 return Kind == k_VectorList && VectorList.Count == NumRegs &&
943 !VectorList.ElementKind;
944 }
945
946 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
947 bool isTypedVectorList() const {
948 if (Kind != k_VectorList)
949 return false;
950 if (VectorList.Count != NumRegs)
951 return false;
952 if (VectorList.ElementKind != ElementKind)
953 return false;
954 return VectorList.NumElements == NumElements;
955 }
956
957 bool isVectorIndex1() const {
958 return Kind == k_VectorIndex && VectorIndex.Val == 1;
959 }
960 bool isVectorIndexB() const {
961 return Kind == k_VectorIndex && VectorIndex.Val < 16;
962 }
963 bool isVectorIndexH() const {
964 return Kind == k_VectorIndex && VectorIndex.Val < 8;
965 }
966 bool isVectorIndexS() const {
967 return Kind == k_VectorIndex && VectorIndex.Val < 4;
968 }
969 bool isVectorIndexD() const {
970 return Kind == k_VectorIndex && VectorIndex.Val < 2;
971 }
972 bool isToken() const override { return Kind == k_Token; }
973 bool isTokenEqual(StringRef Str) const {
974 return Kind == k_Token && getToken() == Str;
975 }
976 bool isSysCR() const { return Kind == k_SysCR; }
977 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000978 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000979 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
980 bool isShifter() const {
981 if (!isShiftExtend())
982 return false;
983
984 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
985 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
986 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
987 ST == AArch64_AM::MSL);
988 }
989 bool isExtend() const {
990 if (!isShiftExtend())
991 return false;
992
993 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
994 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
995 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
996 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
997 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
998 ET == AArch64_AM::LSL) &&
999 getShiftExtendAmount() <= 4;
1000 }
1001
1002 bool isExtend64() const {
1003 if (!isExtend())
1004 return false;
1005 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1006 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1007 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1008 }
1009 bool isExtendLSL64() const {
1010 if (!isExtend())
1011 return false;
1012 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1013 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1014 ET == AArch64_AM::LSL) &&
1015 getShiftExtendAmount() <= 4;
1016 }
1017
1018 template<int Width> bool isMemXExtend() const {
1019 if (!isExtend())
1020 return false;
1021 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1022 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1023 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1024 getShiftExtendAmount() == 0);
1025 }
1026
1027 template<int Width> bool isMemWExtend() const {
1028 if (!isExtend())
1029 return false;
1030 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1031 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1032 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1033 getShiftExtendAmount() == 0);
1034 }
1035
1036 template <unsigned width>
1037 bool isArithmeticShifter() const {
1038 if (!isShifter())
1039 return false;
1040
1041 // An arithmetic shifter is LSL, LSR, or ASR.
1042 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1043 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1044 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1045 }
1046
1047 template <unsigned width>
1048 bool isLogicalShifter() const {
1049 if (!isShifter())
1050 return false;
1051
1052 // A logical shifter is LSL, LSR, ASR or ROR.
1053 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1054 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1055 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1056 getShiftExtendAmount() < width;
1057 }
1058
1059 bool isMovImm32Shifter() const {
1060 if (!isShifter())
1061 return false;
1062
1063 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1064 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1065 if (ST != AArch64_AM::LSL)
1066 return false;
1067 uint64_t Val = getShiftExtendAmount();
1068 return (Val == 0 || Val == 16);
1069 }
1070
1071 bool isMovImm64Shifter() const {
1072 if (!isShifter())
1073 return false;
1074
1075 // A MOVi shifter is LSL of 0 or 16.
1076 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1077 if (ST != AArch64_AM::LSL)
1078 return false;
1079 uint64_t Val = getShiftExtendAmount();
1080 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1081 }
1082
1083 bool isLogicalVecShifter() const {
1084 if (!isShifter())
1085 return false;
1086
1087 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1088 unsigned Shift = getShiftExtendAmount();
1089 return getShiftExtendType() == AArch64_AM::LSL &&
1090 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1091 }
1092
1093 bool isLogicalVecHalfWordShifter() const {
1094 if (!isLogicalVecShifter())
1095 return false;
1096
1097 // A logical vector shifter is a left shift by 0 or 8.
1098 unsigned Shift = getShiftExtendAmount();
1099 return getShiftExtendType() == AArch64_AM::LSL &&
1100 (Shift == 0 || Shift == 8);
1101 }
1102
1103 bool isMoveVecShifter() const {
1104 if (!isShiftExtend())
1105 return false;
1106
1107 // A logical vector shifter is a left shift by 8 or 16.
1108 unsigned Shift = getShiftExtendAmount();
1109 return getShiftExtendType() == AArch64_AM::MSL &&
1110 (Shift == 8 || Shift == 16);
1111 }
1112
1113 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1114 // to LDUR/STUR when the offset is not legal for the former but is for
1115 // the latter. As such, in addition to checking for being a legal unscaled
1116 // address, also check that it is not a legal scaled address. This avoids
1117 // ambiguity in the matcher.
1118 template<int Width>
1119 bool isSImm9OffsetFB() const {
1120 return isSImm9() && !isUImm12Offset<Width / 8>();
1121 }
1122
1123 bool isAdrpLabel() const {
1124 // Validation was handled during parsing, so we just sanity check that
1125 // something didn't go haywire.
1126 if (!isImm())
1127 return false;
1128
1129 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1130 int64_t Val = CE->getValue();
1131 int64_t Min = - (4096 * (1LL << (21 - 1)));
1132 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1133 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1134 }
1135
1136 return true;
1137 }
1138
1139 bool isAdrLabel() const {
1140 // Validation was handled during parsing, so we just sanity check that
1141 // something didn't go haywire.
1142 if (!isImm())
1143 return false;
1144
1145 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1146 int64_t Val = CE->getValue();
1147 int64_t Min = - (1LL << (21 - 1));
1148 int64_t Max = ((1LL << (21 - 1)) - 1);
1149 return Val >= Min && Val <= Max;
1150 }
1151
1152 return true;
1153 }
1154
1155 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1156 // Add as immediates when possible. Null MCExpr = 0.
1157 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001158 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001159 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001160 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001161 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001162 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001163 }
1164
1165 void addRegOperands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001167 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001168 }
1169
1170 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 assert(
1173 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1174
1175 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1176 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1177 RI->getEncodingValue(getReg()));
1178
Jim Grosbache9119e42015-05-13 18:37:00 +00001179 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001180 }
1181
1182 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1183 assert(N == 1 && "Invalid number of operands!");
1184 assert(
1185 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001186 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001187 }
1188
1189 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
1191 assert(
1192 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001193 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001194 }
1195
1196 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001198 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001199 }
1200
1201 template <unsigned NumRegs>
1202 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1203 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001204 static const unsigned FirstRegs[] = { AArch64::D0,
1205 AArch64::D0_D1,
1206 AArch64::D0_D1_D2,
1207 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001208 unsigned FirstReg = FirstRegs[NumRegs - 1];
1209
1210 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001211 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001212 }
1213
1214 template <unsigned NumRegs>
1215 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1216 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001217 static const unsigned FirstRegs[] = { AArch64::Q0,
1218 AArch64::Q0_Q1,
1219 AArch64::Q0_Q1_Q2,
1220 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001221 unsigned FirstReg = FirstRegs[NumRegs - 1];
1222
1223 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001224 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001225 }
1226
1227 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1228 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001229 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001230 }
1231
1232 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1233 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001234 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001235 }
1236
1237 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1238 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001239 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001240 }
1241
1242 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1243 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001244 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001245 }
1246
1247 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001249 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001250 }
1251
1252 void addImmOperands(MCInst &Inst, unsigned N) const {
1253 assert(N == 1 && "Invalid number of operands!");
1254 // If this is a pageoff symrefexpr with an addend, adjust the addend
1255 // to be only the page-offset portion. Otherwise, just add the expr
1256 // as-is.
1257 addExpr(Inst, getImm());
1258 }
1259
1260 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1261 assert(N == 2 && "Invalid number of operands!");
1262 if (isShiftedImm()) {
1263 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001264 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001265 } else {
1266 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001267 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001268 }
1269 }
1270
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001271 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1272 assert(N == 2 && "Invalid number of operands!");
1273
1274 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1275 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1276 int64_t Val = -CE->getValue();
1277 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1278
1279 Inst.addOperand(MCOperand::createImm(Val));
1280 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1281 }
1282
Tim Northover3b0846e2014-05-24 12:50:23 +00001283 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1284 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001285 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001286 }
1287
1288 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1289 assert(N == 1 && "Invalid number of operands!");
1290 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1291 if (!MCE)
1292 addExpr(Inst, getImm());
1293 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001294 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001295 }
1296
1297 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1298 addImmOperands(Inst, N);
1299 }
1300
1301 template<int Scale>
1302 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1303 assert(N == 1 && "Invalid number of operands!");
1304 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1305
1306 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001307 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001308 return;
1309 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001310 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001311 }
1312
1313 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1314 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001315 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001316 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001317 }
1318
1319 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1320 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001321 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001322 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001323 }
1324
1325 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1326 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001327 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001328 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001329 }
1330
1331 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1332 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001333 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001334 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001335 }
1336
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001337 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1338 assert(N == 1 && "Invalid number of operands!");
1339 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1340 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1341 }
1342
Tim Northover3b0846e2014-05-24 12:50:23 +00001343 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1344 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001345 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001346 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001347 }
1348
1349 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1350 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001351 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001352 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001353 }
1354
1355 void addImm0_15Operands(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());
Jim Grosbache9119e42015-05-13 18:37:00 +00001358 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001359 }
1360
1361 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1362 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001363 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001364 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001365 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001366 }
1367
1368 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001370 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001371 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001372 }
1373
1374 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1375 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001376 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001377 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001378 }
1379
1380 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001382 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001383 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001384 }
1385
1386 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1387 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001388 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001389 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 }
1391
1392 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1393 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001394 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001395 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001396 }
1397
1398 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1399 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001400 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001401 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001402 }
1403
1404 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001406 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001407 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001408 }
1409
1410 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1411 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001412 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001413 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001414 }
1415
1416 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1417 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001418 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001419 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001420 }
1421
1422 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1423 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001424 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001425 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001426 }
1427
1428 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1429 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001430 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001431 uint64_t encoding =
1432 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001438 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001439 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001440 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001441 }
1442
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001443 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1444 assert(N == 1 && "Invalid number of operands!");
1445 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1446 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1447 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001448 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001449 }
1450
1451 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1454 uint64_t encoding =
1455 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001456 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001457 }
1458
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1460 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001461 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001462 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001463 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 }
1465
1466 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1467 // Branch operands don't encode the low bits, so shift them off
1468 // here. If it's a label, however, just put it on directly as there's
1469 // not enough information now to do anything.
1470 assert(N == 1 && "Invalid number of operands!");
1471 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1472 if (!MCE) {
1473 addExpr(Inst, getImm());
1474 return;
1475 }
1476 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001477 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001478 }
1479
1480 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1481 // Branch operands don't encode the low bits, so shift them off
1482 // here. If it's a label, however, just put it on directly as there's
1483 // not enough information now to do anything.
1484 assert(N == 1 && "Invalid number of operands!");
1485 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1486 if (!MCE) {
1487 addExpr(Inst, getImm());
1488 return;
1489 }
1490 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
1494 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1495 // Branch operands don't encode the low bits, so shift them off
1496 // here. If it's a label, however, just put it on directly as there's
1497 // not enough information now to do anything.
1498 assert(N == 1 && "Invalid number of operands!");
1499 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1500 if (!MCE) {
1501 addExpr(Inst, getImm());
1502 return;
1503 }
1504 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001505 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001506 }
1507
1508 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1509 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001510 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001511 }
1512
1513 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1514 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001515 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 }
1517
1518 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1519 assert(N == 1 && "Invalid number of operands!");
1520
Jim Grosbache9119e42015-05-13 18:37:00 +00001521 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001522 }
1523
1524 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526
Jim Grosbache9119e42015-05-13 18:37:00 +00001527 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001530 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1531 assert(N == 1 && "Invalid number of operands!");
1532
1533 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1534 }
1535
1536 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001537 assert(N == 1 && "Invalid number of operands!");
1538
Jim Grosbache9119e42015-05-13 18:37:00 +00001539 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 }
1541
1542 void addSysCROperands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001544 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001545 }
1546
1547 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001549 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001550 }
1551
Oliver Stannarda34e4702015-12-01 10:48:51 +00001552 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1555 }
1556
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 void addShifterOperands(MCInst &Inst, unsigned N) const {
1558 assert(N == 1 && "Invalid number of operands!");
1559 unsigned Imm =
1560 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001561 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001562 }
1563
1564 void addExtendOperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1567 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1568 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001569 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001570 }
1571
1572 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1573 assert(N == 1 && "Invalid number of operands!");
1574 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1575 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1576 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001577 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001578 }
1579
1580 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 2 && "Invalid number of operands!");
1582 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1583 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001584 Inst.addOperand(MCOperand::createImm(IsSigned));
1585 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001586 }
1587
1588 // For 8-bit load/store instructions with a register offset, both the
1589 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1590 // they're disambiguated by whether the shift was explicit or implicit rather
1591 // than its size.
1592 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1593 assert(N == 2 && "Invalid number of operands!");
1594 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1595 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001596 Inst.addOperand(MCOperand::createImm(IsSigned));
1597 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001598 }
1599
1600 template<int Shift>
1601 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1602 assert(N == 1 && "Invalid number of operands!");
1603
1604 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1605 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001606 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001607 }
1608
1609 template<int Shift>
1610 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1611 assert(N == 1 && "Invalid number of operands!");
1612
1613 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1614 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001615 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001616 }
1617
1618 void print(raw_ostream &OS) const override;
1619
David Blaikie960ea3f2014-06-08 16:18:35 +00001620 static std::unique_ptr<AArch64Operand>
1621 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1622 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001623 Op->Tok.Data = Str.data();
1624 Op->Tok.Length = Str.size();
1625 Op->Tok.IsSuffix = IsSuffix;
1626 Op->StartLoc = S;
1627 Op->EndLoc = S;
1628 return Op;
1629 }
1630
David Blaikie960ea3f2014-06-08 16:18:35 +00001631 static std::unique_ptr<AArch64Operand>
1632 CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
1633 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001634 Op->Reg.RegNum = RegNum;
1635 Op->Reg.isVector = isVector;
1636 Op->StartLoc = S;
1637 Op->EndLoc = E;
1638 return Op;
1639 }
1640
David Blaikie960ea3f2014-06-08 16:18:35 +00001641 static std::unique_ptr<AArch64Operand>
1642 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1643 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1644 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001645 Op->VectorList.RegNum = RegNum;
1646 Op->VectorList.Count = Count;
1647 Op->VectorList.NumElements = NumElements;
1648 Op->VectorList.ElementKind = ElementKind;
1649 Op->StartLoc = S;
1650 Op->EndLoc = E;
1651 return Op;
1652 }
1653
David Blaikie960ea3f2014-06-08 16:18:35 +00001654 static std::unique_ptr<AArch64Operand>
1655 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1656 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001657 Op->VectorIndex.Val = Idx;
1658 Op->StartLoc = S;
1659 Op->EndLoc = E;
1660 return Op;
1661 }
1662
David Blaikie960ea3f2014-06-08 16:18:35 +00001663 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1664 SMLoc E, MCContext &Ctx) {
1665 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001666 Op->Imm.Val = Val;
1667 Op->StartLoc = S;
1668 Op->EndLoc = E;
1669 return Op;
1670 }
1671
David Blaikie960ea3f2014-06-08 16:18:35 +00001672 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1673 unsigned ShiftAmount,
1674 SMLoc S, SMLoc E,
1675 MCContext &Ctx) {
1676 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001677 Op->ShiftedImm .Val = Val;
1678 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1679 Op->StartLoc = S;
1680 Op->EndLoc = E;
1681 return Op;
1682 }
1683
David Blaikie960ea3f2014-06-08 16:18:35 +00001684 static std::unique_ptr<AArch64Operand>
1685 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1686 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001687 Op->CondCode.Code = Code;
1688 Op->StartLoc = S;
1689 Op->EndLoc = E;
1690 return Op;
1691 }
1692
David Blaikie960ea3f2014-06-08 16:18:35 +00001693 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1694 MCContext &Ctx) {
1695 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001696 Op->FPImm.Val = Val;
1697 Op->StartLoc = S;
1698 Op->EndLoc = S;
1699 return Op;
1700 }
1701
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001702 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1703 StringRef Str,
1704 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001705 MCContext &Ctx) {
1706 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001707 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001708 Op->Barrier.Data = Str.data();
1709 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001710 Op->StartLoc = S;
1711 Op->EndLoc = S;
1712 return Op;
1713 }
1714
Tim Northover7cd58932015-01-22 17:23:04 +00001715 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1716 uint32_t MRSReg,
1717 uint32_t MSRReg,
1718 uint32_t PStateField,
1719 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001720 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001721 Op->SysReg.Data = Str.data();
1722 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001723 Op->SysReg.MRSReg = MRSReg;
1724 Op->SysReg.MSRReg = MSRReg;
1725 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001726 Op->StartLoc = S;
1727 Op->EndLoc = S;
1728 return Op;
1729 }
1730
David Blaikie960ea3f2014-06-08 16:18:35 +00001731 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1732 SMLoc E, MCContext &Ctx) {
1733 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001734 Op->SysCRImm.Val = Val;
1735 Op->StartLoc = S;
1736 Op->EndLoc = E;
1737 return Op;
1738 }
1739
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001740 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1741 StringRef Str,
1742 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001743 MCContext &Ctx) {
1744 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001745 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001746 Op->Barrier.Data = Str.data();
1747 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001748 Op->StartLoc = S;
1749 Op->EndLoc = S;
1750 return Op;
1751 }
1752
Oliver Stannarda34e4702015-12-01 10:48:51 +00001753 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1754 StringRef Str,
1755 SMLoc S,
1756 MCContext &Ctx) {
1757 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1758 Op->PSBHint.Val = Val;
1759 Op->PSBHint.Data = Str.data();
1760 Op->PSBHint.Length = Str.size();
1761 Op->StartLoc = S;
1762 Op->EndLoc = S;
1763 return Op;
1764 }
1765
David Blaikie960ea3f2014-06-08 16:18:35 +00001766 static std::unique_ptr<AArch64Operand>
1767 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1768 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1769 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001770 Op->ShiftExtend.Type = ShOp;
1771 Op->ShiftExtend.Amount = Val;
1772 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1773 Op->StartLoc = S;
1774 Op->EndLoc = E;
1775 return Op;
1776 }
1777};
1778
1779} // end anonymous namespace.
1780
1781void AArch64Operand::print(raw_ostream &OS) const {
1782 switch (Kind) {
1783 case k_FPImm:
1784 OS << "<fpimm " << getFPImm() << "("
1785 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1786 break;
1787 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001788 StringRef Name = getBarrierName();
1789 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001790 OS << "<barrier " << Name << ">";
1791 else
1792 OS << "<barrier invalid #" << getBarrier() << ">";
1793 break;
1794 }
1795 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001796 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001797 break;
1798 case k_ShiftedImm: {
1799 unsigned Shift = getShiftedImmShift();
1800 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001801 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001802 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1803 break;
1804 }
1805 case k_CondCode:
1806 OS << "<condcode " << getCondCode() << ">";
1807 break;
1808 case k_Register:
1809 OS << "<register " << getReg() << ">";
1810 break;
1811 case k_VectorList: {
1812 OS << "<vectorlist ";
1813 unsigned Reg = getVectorListStart();
1814 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1815 OS << Reg + i << " ";
1816 OS << ">";
1817 break;
1818 }
1819 case k_VectorIndex:
1820 OS << "<vectorindex " << getVectorIndex() << ">";
1821 break;
1822 case k_SysReg:
1823 OS << "<sysreg: " << getSysReg() << '>';
1824 break;
1825 case k_Token:
1826 OS << "'" << getToken() << "'";
1827 break;
1828 case k_SysCR:
1829 OS << "c" << getSysCR();
1830 break;
1831 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001832 StringRef Name = getPrefetchName();
1833 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001834 OS << "<prfop " << Name << ">";
1835 else
1836 OS << "<prfop invalid #" << getPrefetch() << ">";
1837 break;
1838 }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001839 case k_PSBHint: {
1840 OS << getPSBHintName();
1841 break;
1842 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001843 case k_ShiftExtend: {
1844 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1845 << getShiftExtendAmount();
1846 if (!hasShiftExtendAmount())
1847 OS << "<imp>";
1848 OS << '>';
1849 break;
1850 }
1851 }
1852}
1853
1854/// @name Auto-generated Match Functions
1855/// {
1856
1857static unsigned MatchRegisterName(StringRef Name);
1858
1859/// }
1860
1861static unsigned matchVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001862 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001863 .Case("v0", AArch64::Q0)
1864 .Case("v1", AArch64::Q1)
1865 .Case("v2", AArch64::Q2)
1866 .Case("v3", AArch64::Q3)
1867 .Case("v4", AArch64::Q4)
1868 .Case("v5", AArch64::Q5)
1869 .Case("v6", AArch64::Q6)
1870 .Case("v7", AArch64::Q7)
1871 .Case("v8", AArch64::Q8)
1872 .Case("v9", AArch64::Q9)
1873 .Case("v10", AArch64::Q10)
1874 .Case("v11", AArch64::Q11)
1875 .Case("v12", AArch64::Q12)
1876 .Case("v13", AArch64::Q13)
1877 .Case("v14", AArch64::Q14)
1878 .Case("v15", AArch64::Q15)
1879 .Case("v16", AArch64::Q16)
1880 .Case("v17", AArch64::Q17)
1881 .Case("v18", AArch64::Q18)
1882 .Case("v19", AArch64::Q19)
1883 .Case("v20", AArch64::Q20)
1884 .Case("v21", AArch64::Q21)
1885 .Case("v22", AArch64::Q22)
1886 .Case("v23", AArch64::Q23)
1887 .Case("v24", AArch64::Q24)
1888 .Case("v25", AArch64::Q25)
1889 .Case("v26", AArch64::Q26)
1890 .Case("v27", AArch64::Q27)
1891 .Case("v28", AArch64::Q28)
1892 .Case("v29", AArch64::Q29)
1893 .Case("v30", AArch64::Q30)
1894 .Case("v31", AArch64::Q31)
1895 .Default(0);
1896}
1897
1898static bool isValidVectorKind(StringRef Name) {
1899 return StringSwitch<bool>(Name.lower())
1900 .Case(".8b", true)
1901 .Case(".16b", true)
1902 .Case(".4h", true)
1903 .Case(".8h", true)
1904 .Case(".2s", true)
1905 .Case(".4s", true)
1906 .Case(".1d", true)
1907 .Case(".2d", true)
1908 .Case(".1q", true)
1909 // Accept the width neutral ones, too, for verbose syntax. If those
1910 // aren't used in the right places, the token operand won't match so
1911 // all will work out.
1912 .Case(".b", true)
1913 .Case(".h", true)
1914 .Case(".s", true)
1915 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001916 // Needed for fp16 scalar pairwise reductions
1917 .Case(".2h", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001918 .Default(false);
1919}
1920
1921static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1922 char &ElementKind) {
1923 assert(isValidVectorKind(Name));
1924
1925 ElementKind = Name.lower()[Name.size() - 1];
1926 NumElements = 0;
1927
1928 if (Name.size() == 2)
1929 return;
1930
1931 // Parse the lane count
1932 Name = Name.drop_front();
1933 while (isdigit(Name.front())) {
1934 NumElements = 10 * NumElements + (Name.front() - '0');
1935 Name = Name.drop_front();
1936 }
1937}
1938
1939bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1940 SMLoc &EndLoc) {
1941 StartLoc = getLoc();
1942 RegNo = tryParseRegister();
1943 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1944 return (RegNo == (unsigned)-1);
1945}
1946
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001947// Matches a register name or register alias previously defined by '.req'
1948unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
1949 bool isVector) {
1950 unsigned RegNum = isVector ? matchVectorRegName(Name)
1951 : MatchRegisterName(Name);
1952
1953 if (RegNum == 0) {
1954 // Check for aliases registered via .req. Canonicalize to lower case.
1955 // That's more consistent since register names are case insensitive, and
1956 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1957 auto Entry = RegisterReqs.find(Name.lower());
1958 if (Entry == RegisterReqs.end())
1959 return 0;
1960 // set RegNum if the match is the right kind of register
1961 if (isVector == Entry->getValue().first)
1962 RegNum = Entry->getValue().second;
1963 }
1964 return RegNum;
1965}
1966
Tim Northover3b0846e2014-05-24 12:50:23 +00001967/// tryParseRegister - Try to parse a register name. The token must be an
1968/// Identifier when called, and if it is a register name the token is eaten and
1969/// the register is added to the operand list.
1970int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001971 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001972 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001973 if (Tok.isNot(AsmToken::Identifier))
1974 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00001975
1976 std::string lowerCase = Tok.getString().lower();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001977 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
Tim Northover3b0846e2014-05-24 12:50:23 +00001978 // Also handle a few aliases of registers.
1979 if (RegNum == 0)
1980 RegNum = StringSwitch<unsigned>(lowerCase)
1981 .Case("fp", AArch64::FP)
1982 .Case("lr", AArch64::LR)
1983 .Case("x31", AArch64::XZR)
1984 .Case("w31", AArch64::WZR)
1985 .Default(0);
1986
1987 if (RegNum == 0)
1988 return -1;
1989
1990 Parser.Lex(); // Eat identifier token.
1991 return RegNum;
1992}
1993
1994/// tryMatchVectorRegister - Try to parse a vector register name with optional
1995/// kind specifier. If it is a register specifier, eat the token and return it.
1996int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001997 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001998 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1999 TokError("vector register expected");
2000 return -1;
2001 }
2002
2003 StringRef Name = Parser.getTok().getString();
2004 // If there is a kind specifier, it's separated from the register name by
2005 // a '.'.
2006 size_t Start = 0, Next = Name.find('.');
2007 StringRef Head = Name.slice(Start, Next);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002008 unsigned RegNum = matchRegisterNameAlias(Head, true);
2009
Tim Northover3b0846e2014-05-24 12:50:23 +00002010 if (RegNum) {
2011 if (Next != StringRef::npos) {
2012 Kind = Name.slice(Next, StringRef::npos);
2013 if (!isValidVectorKind(Kind)) {
2014 TokError("invalid vector kind qualifier");
2015 return -1;
2016 }
2017 }
2018 Parser.Lex(); // Eat the register token.
2019 return RegNum;
2020 }
2021
2022 if (expected)
2023 TokError("vector register expected");
2024 return -1;
2025}
2026
2027/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002028OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002029AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002030 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002031 SMLoc S = getLoc();
2032
2033 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2034 Error(S, "Expected cN operand where 0 <= N <= 15");
2035 return MatchOperand_ParseFail;
2036 }
2037
2038 StringRef Tok = Parser.getTok().getIdentifier();
2039 if (Tok[0] != 'c' && Tok[0] != 'C') {
2040 Error(S, "Expected cN operand where 0 <= N <= 15");
2041 return MatchOperand_ParseFail;
2042 }
2043
2044 uint32_t CRNum;
2045 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2046 if (BadNum || CRNum > 15) {
2047 Error(S, "Expected cN operand where 0 <= N <= 15");
2048 return MatchOperand_ParseFail;
2049 }
2050
2051 Parser.Lex(); // Eat identifier token.
2052 Operands.push_back(
2053 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2054 return MatchOperand_Success;
2055}
2056
2057/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002058OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002059AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002060 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002061 SMLoc S = getLoc();
2062 const AsmToken &Tok = Parser.getTok();
2063 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002064 // Eat optional hash.
2065 if (parseOptionalToken(AsmToken::Hash) ||
2066 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002067 const MCExpr *ImmVal;
2068 if (getParser().parseExpression(ImmVal))
2069 return MatchOperand_ParseFail;
2070
2071 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2072 if (!MCE) {
2073 TokError("immediate value expected for prefetch operand");
2074 return MatchOperand_ParseFail;
2075 }
2076 unsigned prfop = MCE->getValue();
2077 if (prfop > 31) {
2078 TokError("prefetch operand out of range, [0,31] expected");
2079 return MatchOperand_ParseFail;
2080 }
2081
Tim Northovere6ae6762016-07-05 21:23:04 +00002082 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2083 Operands.push_back(AArch64Operand::CreatePrefetch(
2084 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002085 return MatchOperand_Success;
2086 }
2087
2088 if (Tok.isNot(AsmToken::Identifier)) {
2089 TokError("pre-fetch hint expected");
2090 return MatchOperand_ParseFail;
2091 }
2092
Tim Northovere6ae6762016-07-05 21:23:04 +00002093 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2094 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002095 TokError("pre-fetch hint expected");
2096 return MatchOperand_ParseFail;
2097 }
2098
2099 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002100 Operands.push_back(AArch64Operand::CreatePrefetch(
2101 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002102 return MatchOperand_Success;
2103}
2104
Oliver Stannarda34e4702015-12-01 10:48:51 +00002105/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002106OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002107AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2108 MCAsmParser &Parser = getParser();
2109 SMLoc S = getLoc();
2110 const AsmToken &Tok = Parser.getTok();
2111 if (Tok.isNot(AsmToken::Identifier)) {
2112 TokError("invalid operand for instruction");
2113 return MatchOperand_ParseFail;
2114 }
2115
Tim Northovere6ae6762016-07-05 21:23:04 +00002116 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2117 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002118 TokError("invalid operand for instruction");
2119 return MatchOperand_ParseFail;
2120 }
2121
2122 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002123 Operands.push_back(AArch64Operand::CreatePSBHint(
2124 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002125 return MatchOperand_Success;
2126}
2127
Tim Northover3b0846e2014-05-24 12:50:23 +00002128/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2129/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002130OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002131AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002132 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002133 SMLoc S = getLoc();
2134 const MCExpr *Expr;
2135
2136 if (Parser.getTok().is(AsmToken::Hash)) {
2137 Parser.Lex(); // Eat hash token.
2138 }
2139
2140 if (parseSymbolicImmVal(Expr))
2141 return MatchOperand_ParseFail;
2142
2143 AArch64MCExpr::VariantKind ELFRefKind;
2144 MCSymbolRefExpr::VariantKind DarwinRefKind;
2145 int64_t Addend;
2146 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2147 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2148 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2149 // No modifier was specified at all; this is the syntax for an ELF basic
2150 // ADRP relocation (unfortunately).
2151 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002152 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002153 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2154 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2155 Addend != 0) {
2156 Error(S, "gotpage label reference not allowed an addend");
2157 return MatchOperand_ParseFail;
2158 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2159 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2160 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2161 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2162 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2163 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2164 // The operand must be an @page or @gotpage qualified symbolref.
2165 Error(S, "page or gotpage label reference expected");
2166 return MatchOperand_ParseFail;
2167 }
2168 }
2169
2170 // We have either a label reference possibly with addend or an immediate. The
2171 // addend is a raw value here. The linker will adjust it to only reference the
2172 // page.
2173 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2174 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2175
2176 return MatchOperand_Success;
2177}
2178
2179/// tryParseAdrLabel - Parse and validate a source label for the ADR
2180/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002181OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002182AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2183 SMLoc S = getLoc();
2184 const MCExpr *Expr;
2185
Nirav Davee833c6c2016-11-08 18:31:04 +00002186 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002187 if (getParser().parseExpression(Expr))
2188 return MatchOperand_ParseFail;
2189
2190 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2191 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2192
2193 return MatchOperand_Success;
2194}
2195
2196/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002197OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002198AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002199 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002200 SMLoc S = getLoc();
2201
Nirav Davee833c6c2016-11-08 18:31:04 +00002202 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002203
2204 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002205 bool isNegative = parseOptionalToken(AsmToken::Minus);
2206
Tim Northover3b0846e2014-05-24 12:50:23 +00002207 const AsmToken &Tok = Parser.getTok();
2208 if (Tok.is(AsmToken::Real)) {
2209 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002210 if (isNegative)
2211 RealVal.changeSign();
2212
Tim Northover3b0846e2014-05-24 12:50:23 +00002213 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002214 int Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2215 Parser.Lex(); // Eat the token.
2216 // Check for out of range values. As an exception, we let Zero through,
2217 // as we handle that special case in post-processing before matching in
2218 // order to use the zero register for it.
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002219 if (Val == -1 && !RealVal.isPosZero()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002220 TokError("expected compatible register or floating-point constant");
2221 return MatchOperand_ParseFail;
2222 }
2223 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2224 return MatchOperand_Success;
2225 }
2226 if (Tok.is(AsmToken::Integer)) {
2227 int64_t Val;
2228 if (!isNegative && Tok.getString().startswith("0x")) {
2229 Val = Tok.getIntVal();
2230 if (Val > 255 || Val < 0) {
2231 TokError("encoded floating point value out of range");
2232 return MatchOperand_ParseFail;
2233 }
2234 } else {
2235 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
2236 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2237 // If we had a '-' in front, toggle the sign bit.
2238 IntVal ^= (uint64_t)isNegative << 63;
2239 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2240 }
2241 Parser.Lex(); // Eat the token.
2242 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2243 return MatchOperand_Success;
2244 }
2245
2246 if (!Hash)
2247 return MatchOperand_NoMatch;
2248
2249 TokError("invalid floating point immediate");
2250 return MatchOperand_ParseFail;
2251}
2252
2253/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002254OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002255AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002256 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002257 SMLoc S = getLoc();
2258
2259 if (Parser.getTok().is(AsmToken::Hash))
2260 Parser.Lex(); // Eat '#'
2261 else if (Parser.getTok().isNot(AsmToken::Integer))
2262 // Operand should start from # or should be integer, emit error otherwise.
2263 return MatchOperand_NoMatch;
2264
2265 const MCExpr *Imm;
2266 if (parseSymbolicImmVal(Imm))
2267 return MatchOperand_ParseFail;
2268 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2269 uint64_t ShiftAmount = 0;
2270 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2271 if (MCE) {
2272 int64_t Val = MCE->getValue();
2273 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002274 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002275 ShiftAmount = 12;
2276 }
2277 }
2278 SMLoc E = Parser.getTok().getLoc();
2279 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2280 getContext()));
2281 return MatchOperand_Success;
2282 }
2283
2284 // Eat ','
2285 Parser.Lex();
2286
2287 // The optional operand must be "lsl #N" where N is non-negative.
2288 if (!Parser.getTok().is(AsmToken::Identifier) ||
2289 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2290 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2291 return MatchOperand_ParseFail;
2292 }
2293
2294 // Eat 'lsl'
2295 Parser.Lex();
2296
Nirav Davee833c6c2016-11-08 18:31:04 +00002297 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002298
2299 if (Parser.getTok().isNot(AsmToken::Integer)) {
2300 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2301 return MatchOperand_ParseFail;
2302 }
2303
2304 int64_t ShiftAmount = Parser.getTok().getIntVal();
2305
2306 if (ShiftAmount < 0) {
2307 Error(Parser.getTok().getLoc(), "positive shift amount required");
2308 return MatchOperand_ParseFail;
2309 }
2310 Parser.Lex(); // Eat the number
2311
2312 SMLoc E = Parser.getTok().getLoc();
2313 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2314 S, E, getContext()));
2315 return MatchOperand_Success;
2316}
2317
2318/// parseCondCodeString - Parse a Condition Code string.
2319AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2320 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2321 .Case("eq", AArch64CC::EQ)
2322 .Case("ne", AArch64CC::NE)
2323 .Case("cs", AArch64CC::HS)
2324 .Case("hs", AArch64CC::HS)
2325 .Case("cc", AArch64CC::LO)
2326 .Case("lo", AArch64CC::LO)
2327 .Case("mi", AArch64CC::MI)
2328 .Case("pl", AArch64CC::PL)
2329 .Case("vs", AArch64CC::VS)
2330 .Case("vc", AArch64CC::VC)
2331 .Case("hi", AArch64CC::HI)
2332 .Case("ls", AArch64CC::LS)
2333 .Case("ge", AArch64CC::GE)
2334 .Case("lt", AArch64CC::LT)
2335 .Case("gt", AArch64CC::GT)
2336 .Case("le", AArch64CC::LE)
2337 .Case("al", AArch64CC::AL)
2338 .Case("nv", AArch64CC::NV)
2339 .Default(AArch64CC::Invalid);
2340 return CC;
2341}
2342
2343/// parseCondCode - Parse a Condition Code operand.
2344bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2345 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002346 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002347 SMLoc S = getLoc();
2348 const AsmToken &Tok = Parser.getTok();
2349 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2350
2351 StringRef Cond = Tok.getString();
2352 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2353 if (CC == AArch64CC::Invalid)
2354 return TokError("invalid condition code");
2355 Parser.Lex(); // Eat identifier token.
2356
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002357 if (invertCondCode) {
2358 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2359 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002360 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002361 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002362
2363 Operands.push_back(
2364 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2365 return false;
2366}
2367
2368/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2369/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002370OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002371AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002372 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002373 const AsmToken &Tok = Parser.getTok();
2374 std::string LowerID = Tok.getString().lower();
2375 AArch64_AM::ShiftExtendType ShOp =
2376 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2377 .Case("lsl", AArch64_AM::LSL)
2378 .Case("lsr", AArch64_AM::LSR)
2379 .Case("asr", AArch64_AM::ASR)
2380 .Case("ror", AArch64_AM::ROR)
2381 .Case("msl", AArch64_AM::MSL)
2382 .Case("uxtb", AArch64_AM::UXTB)
2383 .Case("uxth", AArch64_AM::UXTH)
2384 .Case("uxtw", AArch64_AM::UXTW)
2385 .Case("uxtx", AArch64_AM::UXTX)
2386 .Case("sxtb", AArch64_AM::SXTB)
2387 .Case("sxth", AArch64_AM::SXTH)
2388 .Case("sxtw", AArch64_AM::SXTW)
2389 .Case("sxtx", AArch64_AM::SXTX)
2390 .Default(AArch64_AM::InvalidShiftExtend);
2391
2392 if (ShOp == AArch64_AM::InvalidShiftExtend)
2393 return MatchOperand_NoMatch;
2394
2395 SMLoc S = Tok.getLoc();
2396 Parser.Lex();
2397
Nirav Davee833c6c2016-11-08 18:31:04 +00002398 bool Hash = parseOptionalToken(AsmToken::Hash);
2399
Tim Northover3b0846e2014-05-24 12:50:23 +00002400 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2401 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2402 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2403 ShOp == AArch64_AM::MSL) {
2404 // We expect a number here.
2405 TokError("expected #imm after shift specifier");
2406 return MatchOperand_ParseFail;
2407 }
2408
2409 // "extend" type operatoins don't need an immediate, #0 is implicit.
2410 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2411 Operands.push_back(
2412 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2413 return MatchOperand_Success;
2414 }
2415
Jim Grosbach57fd2622014-09-23 22:16:02 +00002416 // Make sure we do actually have a number or a parenthesized expression.
2417 SMLoc E = Parser.getTok().getLoc();
2418 if (!Parser.getTok().is(AsmToken::Integer) &&
2419 !Parser.getTok().is(AsmToken::LParen)) {
2420 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002421 return MatchOperand_ParseFail;
2422 }
2423
2424 const MCExpr *ImmVal;
2425 if (getParser().parseExpression(ImmVal))
2426 return MatchOperand_ParseFail;
2427
2428 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2429 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002430 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002431 return MatchOperand_ParseFail;
2432 }
2433
Jim Grosbach57fd2622014-09-23 22:16:02 +00002434 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002435 Operands.push_back(AArch64Operand::CreateShiftExtend(
2436 ShOp, MCE->getValue(), true, S, E, getContext()));
2437 return MatchOperand_Success;
2438}
2439
2440/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2441/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2442bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2443 OperandVector &Operands) {
2444 if (Name.find('.') != StringRef::npos)
2445 return TokError("invalid operand");
2446
2447 Mnemonic = Name;
2448 Operands.push_back(
2449 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2450
Rafael Espindola961d4692014-11-11 05:18:41 +00002451 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002452 const AsmToken &Tok = Parser.getTok();
2453 StringRef Op = Tok.getString();
2454 SMLoc S = Tok.getLoc();
2455
2456 const MCExpr *Expr = nullptr;
2457
2458#define SYS_ALIAS(op1, Cn, Cm, op2) \
2459 do { \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002460 Expr = MCConstantExpr::create(op1, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002461 Operands.push_back( \
2462 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2463 Operands.push_back( \
2464 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext())); \
2465 Operands.push_back( \
2466 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext())); \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002467 Expr = MCConstantExpr::create(op2, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002468 Operands.push_back( \
2469 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2470 } while (0)
2471
2472 if (Mnemonic == "ic") {
2473 if (!Op.compare_lower("ialluis")) {
2474 // SYS #0, C7, C1, #0
2475 SYS_ALIAS(0, 7, 1, 0);
2476 } else if (!Op.compare_lower("iallu")) {
2477 // SYS #0, C7, C5, #0
2478 SYS_ALIAS(0, 7, 5, 0);
2479 } else if (!Op.compare_lower("ivau")) {
2480 // SYS #3, C7, C5, #1
2481 SYS_ALIAS(3, 7, 5, 1);
2482 } else {
2483 return TokError("invalid operand for IC instruction");
2484 }
2485 } else if (Mnemonic == "dc") {
2486 if (!Op.compare_lower("zva")) {
2487 // SYS #3, C7, C4, #1
2488 SYS_ALIAS(3, 7, 4, 1);
2489 } else if (!Op.compare_lower("ivac")) {
2490 // SYS #3, C7, C6, #1
2491 SYS_ALIAS(0, 7, 6, 1);
2492 } else if (!Op.compare_lower("isw")) {
2493 // SYS #0, C7, C6, #2
2494 SYS_ALIAS(0, 7, 6, 2);
2495 } else if (!Op.compare_lower("cvac")) {
2496 // SYS #3, C7, C10, #1
2497 SYS_ALIAS(3, 7, 10, 1);
2498 } else if (!Op.compare_lower("csw")) {
2499 // SYS #0, C7, C10, #2
2500 SYS_ALIAS(0, 7, 10, 2);
2501 } else if (!Op.compare_lower("cvau")) {
2502 // SYS #3, C7, C11, #1
2503 SYS_ALIAS(3, 7, 11, 1);
2504 } else if (!Op.compare_lower("civac")) {
2505 // SYS #3, C7, C14, #1
2506 SYS_ALIAS(3, 7, 14, 1);
2507 } else if (!Op.compare_lower("cisw")) {
2508 // SYS #0, C7, C14, #2
2509 SYS_ALIAS(0, 7, 14, 2);
Oliver Stannard1a81cc9f2015-11-26 15:28:47 +00002510 } else if (!Op.compare_lower("cvap")) {
2511 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2512 // SYS #3, C7, C12, #1
2513 SYS_ALIAS(3, 7, 12, 1);
2514 } else {
2515 return TokError("DC CVAP requires ARMv8.2a");
2516 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002517 } else {
2518 return TokError("invalid operand for DC instruction");
2519 }
2520 } else if (Mnemonic == "at") {
2521 if (!Op.compare_lower("s1e1r")) {
2522 // SYS #0, C7, C8, #0
2523 SYS_ALIAS(0, 7, 8, 0);
2524 } else if (!Op.compare_lower("s1e2r")) {
2525 // SYS #4, C7, C8, #0
2526 SYS_ALIAS(4, 7, 8, 0);
2527 } else if (!Op.compare_lower("s1e3r")) {
2528 // SYS #6, C7, C8, #0
2529 SYS_ALIAS(6, 7, 8, 0);
2530 } else if (!Op.compare_lower("s1e1w")) {
2531 // SYS #0, C7, C8, #1
2532 SYS_ALIAS(0, 7, 8, 1);
2533 } else if (!Op.compare_lower("s1e2w")) {
2534 // SYS #4, C7, C8, #1
2535 SYS_ALIAS(4, 7, 8, 1);
2536 } else if (!Op.compare_lower("s1e3w")) {
2537 // SYS #6, C7, C8, #1
2538 SYS_ALIAS(6, 7, 8, 1);
2539 } else if (!Op.compare_lower("s1e0r")) {
2540 // SYS #0, C7, C8, #3
2541 SYS_ALIAS(0, 7, 8, 2);
2542 } else if (!Op.compare_lower("s1e0w")) {
2543 // SYS #0, C7, C8, #3
2544 SYS_ALIAS(0, 7, 8, 3);
2545 } else if (!Op.compare_lower("s12e1r")) {
2546 // SYS #4, C7, C8, #4
2547 SYS_ALIAS(4, 7, 8, 4);
2548 } else if (!Op.compare_lower("s12e1w")) {
2549 // SYS #4, C7, C8, #5
2550 SYS_ALIAS(4, 7, 8, 5);
2551 } else if (!Op.compare_lower("s12e0r")) {
2552 // SYS #4, C7, C8, #6
2553 SYS_ALIAS(4, 7, 8, 6);
2554 } else if (!Op.compare_lower("s12e0w")) {
2555 // SYS #4, C7, C8, #7
2556 SYS_ALIAS(4, 7, 8, 7);
Oliver Stannard64c167d2015-11-26 15:34:44 +00002557 } else if (!Op.compare_lower("s1e1rp")) {
2558 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2559 // SYS #0, C7, C9, #0
2560 SYS_ALIAS(0, 7, 9, 0);
2561 } else {
2562 return TokError("AT S1E1RP requires ARMv8.2a");
2563 }
2564 } else if (!Op.compare_lower("s1e1wp")) {
2565 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2566 // SYS #0, C7, C9, #1
2567 SYS_ALIAS(0, 7, 9, 1);
2568 } else {
2569 return TokError("AT S1E1WP requires ARMv8.2a");
2570 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002571 } else {
2572 return TokError("invalid operand for AT instruction");
2573 }
2574 } else if (Mnemonic == "tlbi") {
2575 if (!Op.compare_lower("vmalle1is")) {
2576 // SYS #0, C8, C3, #0
2577 SYS_ALIAS(0, 8, 3, 0);
2578 } else if (!Op.compare_lower("alle2is")) {
2579 // SYS #4, C8, C3, #0
2580 SYS_ALIAS(4, 8, 3, 0);
2581 } else if (!Op.compare_lower("alle3is")) {
2582 // SYS #6, C8, C3, #0
2583 SYS_ALIAS(6, 8, 3, 0);
2584 } else if (!Op.compare_lower("vae1is")) {
2585 // SYS #0, C8, C3, #1
2586 SYS_ALIAS(0, 8, 3, 1);
2587 } else if (!Op.compare_lower("vae2is")) {
2588 // SYS #4, C8, C3, #1
2589 SYS_ALIAS(4, 8, 3, 1);
2590 } else if (!Op.compare_lower("vae3is")) {
2591 // SYS #6, C8, C3, #1
2592 SYS_ALIAS(6, 8, 3, 1);
2593 } else if (!Op.compare_lower("aside1is")) {
2594 // SYS #0, C8, C3, #2
2595 SYS_ALIAS(0, 8, 3, 2);
2596 } else if (!Op.compare_lower("vaae1is")) {
2597 // SYS #0, C8, C3, #3
2598 SYS_ALIAS(0, 8, 3, 3);
2599 } else if (!Op.compare_lower("alle1is")) {
2600 // SYS #4, C8, C3, #4
2601 SYS_ALIAS(4, 8, 3, 4);
2602 } else if (!Op.compare_lower("vale1is")) {
2603 // SYS #0, C8, C3, #5
2604 SYS_ALIAS(0, 8, 3, 5);
2605 } else if (!Op.compare_lower("vaale1is")) {
2606 // SYS #0, C8, C3, #7
2607 SYS_ALIAS(0, 8, 3, 7);
2608 } else if (!Op.compare_lower("vmalle1")) {
2609 // SYS #0, C8, C7, #0
2610 SYS_ALIAS(0, 8, 7, 0);
2611 } else if (!Op.compare_lower("alle2")) {
2612 // SYS #4, C8, C7, #0
2613 SYS_ALIAS(4, 8, 7, 0);
2614 } else if (!Op.compare_lower("vale2is")) {
2615 // SYS #4, C8, C3, #5
2616 SYS_ALIAS(4, 8, 3, 5);
2617 } else if (!Op.compare_lower("vale3is")) {
2618 // SYS #6, C8, C3, #5
2619 SYS_ALIAS(6, 8, 3, 5);
2620 } else if (!Op.compare_lower("alle3")) {
2621 // SYS #6, C8, C7, #0
2622 SYS_ALIAS(6, 8, 7, 0);
2623 } else if (!Op.compare_lower("vae1")) {
2624 // SYS #0, C8, C7, #1
2625 SYS_ALIAS(0, 8, 7, 1);
2626 } else if (!Op.compare_lower("vae2")) {
2627 // SYS #4, C8, C7, #1
2628 SYS_ALIAS(4, 8, 7, 1);
2629 } else if (!Op.compare_lower("vae3")) {
2630 // SYS #6, C8, C7, #1
2631 SYS_ALIAS(6, 8, 7, 1);
2632 } else if (!Op.compare_lower("aside1")) {
2633 // SYS #0, C8, C7, #2
2634 SYS_ALIAS(0, 8, 7, 2);
2635 } else if (!Op.compare_lower("vaae1")) {
2636 // SYS #0, C8, C7, #3
2637 SYS_ALIAS(0, 8, 7, 3);
2638 } else if (!Op.compare_lower("alle1")) {
2639 // SYS #4, C8, C7, #4
2640 SYS_ALIAS(4, 8, 7, 4);
2641 } else if (!Op.compare_lower("vale1")) {
2642 // SYS #0, C8, C7, #5
2643 SYS_ALIAS(0, 8, 7, 5);
2644 } else if (!Op.compare_lower("vale2")) {
2645 // SYS #4, C8, C7, #5
2646 SYS_ALIAS(4, 8, 7, 5);
2647 } else if (!Op.compare_lower("vale3")) {
2648 // SYS #6, C8, C7, #5
2649 SYS_ALIAS(6, 8, 7, 5);
2650 } else if (!Op.compare_lower("vaale1")) {
2651 // SYS #0, C8, C7, #7
2652 SYS_ALIAS(0, 8, 7, 7);
2653 } else if (!Op.compare_lower("ipas2e1")) {
2654 // SYS #4, C8, C4, #1
2655 SYS_ALIAS(4, 8, 4, 1);
2656 } else if (!Op.compare_lower("ipas2le1")) {
2657 // SYS #4, C8, C4, #5
2658 SYS_ALIAS(4, 8, 4, 5);
2659 } else if (!Op.compare_lower("ipas2e1is")) {
2660 // SYS #4, C8, C4, #1
2661 SYS_ALIAS(4, 8, 0, 1);
2662 } else if (!Op.compare_lower("ipas2le1is")) {
2663 // SYS #4, C8, C4, #5
2664 SYS_ALIAS(4, 8, 0, 5);
2665 } else if (!Op.compare_lower("vmalls12e1")) {
2666 // SYS #4, C8, C7, #6
2667 SYS_ALIAS(4, 8, 7, 6);
2668 } else if (!Op.compare_lower("vmalls12e1is")) {
2669 // SYS #4, C8, C3, #6
2670 SYS_ALIAS(4, 8, 3, 6);
2671 } else {
2672 return TokError("invalid operand for TLBI instruction");
2673 }
2674 }
2675
2676#undef SYS_ALIAS
2677
2678 Parser.Lex(); // Eat operand.
2679
2680 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2681 bool HasRegister = false;
2682
2683 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002684 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002685 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2686 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002687 HasRegister = true;
2688 }
2689
Tim Northover3b0846e2014-05-24 12:50:23 +00002690 if (ExpectRegister && !HasRegister) {
2691 return TokError("specified " + Mnemonic + " op requires a register");
2692 }
2693 else if (!ExpectRegister && HasRegister) {
2694 return TokError("specified " + Mnemonic + " op does not use a register");
2695 }
2696
Nirav Davee833c6c2016-11-08 18:31:04 +00002697 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2698 return true;
2699
Tim Northover3b0846e2014-05-24 12:50:23 +00002700 return false;
2701}
2702
Alex Bradbury58eba092016-11-01 16:32:05 +00002703OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002704AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002705 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002706 const AsmToken &Tok = Parser.getTok();
2707
2708 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002709 if (parseOptionalToken(AsmToken::Hash) ||
2710 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002712 const MCExpr *ImmVal;
2713 SMLoc ExprLoc = getLoc();
2714 if (getParser().parseExpression(ImmVal))
2715 return MatchOperand_ParseFail;
2716 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2717 if (!MCE) {
2718 Error(ExprLoc, "immediate value expected for barrier operand");
2719 return MatchOperand_ParseFail;
2720 }
2721 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2722 Error(ExprLoc, "barrier operand out of range");
2723 return MatchOperand_ParseFail;
2724 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002725 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2726 Operands.push_back(AArch64Operand::CreateBarrier(
2727 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002728 return MatchOperand_Success;
2729 }
2730
2731 if (Tok.isNot(AsmToken::Identifier)) {
2732 TokError("invalid operand for instruction");
2733 return MatchOperand_ParseFail;
2734 }
2735
Tim Northovere6ae6762016-07-05 21:23:04 +00002736 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2737 if (!DB) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002738 TokError("invalid barrier option name");
2739 return MatchOperand_ParseFail;
2740 }
2741
2742 // The only valid named option for ISB is 'sy'
Tim Northovere6ae6762016-07-05 21:23:04 +00002743 if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002744 TokError("'sy' or #imm operand expected");
2745 return MatchOperand_ParseFail;
2746 }
2747
Tim Northovere6ae6762016-07-05 21:23:04 +00002748 Operands.push_back(AArch64Operand::CreateBarrier(
2749 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002750 Parser.Lex(); // Consume the option
2751
2752 return MatchOperand_Success;
2753}
2754
Alex Bradbury58eba092016-11-01 16:32:05 +00002755OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002756AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002757 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002758 const AsmToken &Tok = Parser.getTok();
2759
2760 if (Tok.isNot(AsmToken::Identifier))
2761 return MatchOperand_NoMatch;
2762
Tim Northovere6ae6762016-07-05 21:23:04 +00002763 int MRSReg, MSRReg;
2764 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2765 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2766 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2767 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2768 } else
2769 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002770
Tim Northovere6ae6762016-07-05 21:23:04 +00002771 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2772 unsigned PStateImm = -1;
2773 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2774 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002775
Tim Northovere6ae6762016-07-05 21:23:04 +00002776 Operands.push_back(
2777 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2778 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002779 Parser.Lex(); // Eat identifier
2780
2781 return MatchOperand_Success;
2782}
2783
2784/// tryParseVectorRegister - Parse a vector register operand.
2785bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002786 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002787 if (Parser.getTok().isNot(AsmToken::Identifier))
2788 return true;
2789
2790 SMLoc S = getLoc();
2791 // Check for a vector register specifier first.
2792 StringRef Kind;
2793 int64_t Reg = tryMatchVectorRegister(Kind, false);
2794 if (Reg == -1)
2795 return true;
2796 Operands.push_back(
2797 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2798 // If there was an explicit qualifier, that goes on as a literal text
2799 // operand.
2800 if (!Kind.empty())
2801 Operands.push_back(
2802 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2803
2804 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002805 SMLoc SIdx = getLoc();
2806 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002807 const MCExpr *ImmVal;
2808 if (getParser().parseExpression(ImmVal))
2809 return false;
2810 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2811 if (!MCE) {
2812 TokError("immediate value expected for vector index");
2813 return false;
2814 }
2815
2816 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002817
Nirav Davee833c6c2016-11-08 18:31:04 +00002818 if (parseToken(AsmToken::RBrac, "']' expected"))
2819 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002820
2821 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2822 E, getContext()));
2823 }
2824
2825 return false;
2826}
2827
2828/// parseRegister - Parse a non-vector register operand.
2829bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002830 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002831 SMLoc S = getLoc();
2832 // Try for a vector register.
2833 if (!tryParseVectorRegister(Operands))
2834 return false;
2835
2836 // Try for a scalar register.
2837 int64_t Reg = tryParseRegister();
2838 if (Reg == -1)
2839 return true;
2840 Operands.push_back(
2841 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2842
2843 // A small number of instructions (FMOVXDhighr, for example) have "[1]"
2844 // as a string token in the instruction itself.
Nirav Davee833c6c2016-11-08 18:31:04 +00002845 SMLoc LBracS = getLoc();
2846 const AsmToken &Tok = Parser.getTok();
2847 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002848 if (Tok.is(AsmToken::Integer)) {
2849 SMLoc IntS = getLoc();
2850 int64_t Val = Tok.getIntVal();
2851 if (Val == 1) {
2852 Parser.Lex();
Nirav Davee833c6c2016-11-08 18:31:04 +00002853 SMLoc RBracS = getLoc();
2854 if (parseOptionalToken(AsmToken::RBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002855 Operands.push_back(
2856 AArch64Operand::CreateToken("[", false, LBracS, getContext()));
2857 Operands.push_back(
2858 AArch64Operand::CreateToken("1", false, IntS, getContext()));
2859 Operands.push_back(
2860 AArch64Operand::CreateToken("]", false, RBracS, getContext()));
2861 return false;
2862 }
2863 }
2864 }
2865 }
2866
2867 return false;
2868}
2869
2870bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002871 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002872 bool HasELFModifier = false;
2873 AArch64MCExpr::VariantKind RefKind;
2874
Nirav Davee833c6c2016-11-08 18:31:04 +00002875 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002876 HasELFModifier = true;
2877
Nirav Davee833c6c2016-11-08 18:31:04 +00002878 if (Parser.getTok().isNot(AsmToken::Identifier))
2879 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002880
2881 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2882 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2883 .Case("lo12", AArch64MCExpr::VK_LO12)
2884 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2885 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2886 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2887 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2888 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2889 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2890 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2891 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2892 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2893 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2894 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2895 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2896 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2897 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2898 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2899 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2900 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2901 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2902 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2903 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2904 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2905 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2906 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2907 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2908 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2909 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2910 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2911 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2912 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2913 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2914 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2915 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2916 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2917 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2918 .Default(AArch64MCExpr::VK_INVALID);
2919
Nirav Davee833c6c2016-11-08 18:31:04 +00002920 if (RefKind == AArch64MCExpr::VK_INVALID)
2921 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002922
2923 Parser.Lex(); // Eat identifier
2924
Nirav Davee833c6c2016-11-08 18:31:04 +00002925 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002926 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002927 }
2928
2929 if (getParser().parseExpression(ImmVal))
2930 return true;
2931
2932 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002933 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002934
2935 return false;
2936}
2937
2938/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2939bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002940 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002941 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2942 SMLoc S = getLoc();
2943 Parser.Lex(); // Eat left bracket token.
2944 StringRef Kind;
2945 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2946 if (FirstReg == -1)
2947 return true;
2948 int64_t PrevReg = FirstReg;
2949 unsigned Count = 1;
2950
Nirav Davee833c6c2016-11-08 18:31:04 +00002951 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002952 SMLoc Loc = getLoc();
2953 StringRef NextKind;
2954 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2955 if (Reg == -1)
2956 return true;
2957 // Any Kind suffices must match on all regs in the list.
2958 if (Kind != NextKind)
2959 return Error(Loc, "mismatched register size suffix");
2960
2961 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2962
2963 if (Space == 0 || Space > 3) {
2964 return Error(Loc, "invalid number of vectors");
2965 }
2966
2967 Count += Space;
2968 }
2969 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002970 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002971 SMLoc Loc = getLoc();
2972 StringRef NextKind;
2973 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2974 if (Reg == -1)
2975 return true;
2976 // Any Kind suffices must match on all regs in the list.
2977 if (Kind != NextKind)
2978 return Error(Loc, "mismatched register size suffix");
2979
2980 // Registers must be incremental (with wraparound at 31)
2981 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2982 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2983 return Error(Loc, "registers must be sequential");
2984
2985 PrevReg = Reg;
2986 ++Count;
2987 }
2988 }
2989
Nirav Davee833c6c2016-11-08 18:31:04 +00002990 if (parseToken(AsmToken::RCurly, "'}' expected"))
2991 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002992
2993 if (Count > 4)
2994 return Error(S, "invalid number of vectors");
2995
2996 unsigned NumElements = 0;
2997 char ElementKind = 0;
2998 if (!Kind.empty())
2999 parseValidVectorKind(Kind, NumElements, ElementKind);
3000
3001 Operands.push_back(AArch64Operand::CreateVectorList(
3002 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
3003
3004 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00003005 SMLoc SIdx = getLoc();
3006 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00003007 const MCExpr *ImmVal;
3008 if (getParser().parseExpression(ImmVal))
3009 return false;
3010 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3011 if (!MCE) {
3012 TokError("immediate value expected for vector index");
3013 return false;
3014 }
3015
3016 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003017 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003018 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003019
3020 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3021 E, getContext()));
3022 }
3023 return false;
3024}
3025
Alex Bradbury58eba092016-11-01 16:32:05 +00003026OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003027AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003028 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003029 const AsmToken &Tok = Parser.getTok();
3030 if (!Tok.is(AsmToken::Identifier))
3031 return MatchOperand_NoMatch;
3032
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003033 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00003034
3035 MCContext &Ctx = getContext();
3036 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3037 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3038 return MatchOperand_NoMatch;
3039
3040 SMLoc S = getLoc();
3041 Parser.Lex(); // Eat register
3042
Nirav Davee833c6c2016-11-08 18:31:04 +00003043 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003044 Operands.push_back(
3045 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3046 return MatchOperand_Success;
3047 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003048
Nirav Davee833c6c2016-11-08 18:31:04 +00003049 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003050
3051 if (Parser.getTok().isNot(AsmToken::Integer)) {
3052 Error(getLoc(), "index must be absent or #0");
3053 return MatchOperand_ParseFail;
3054 }
3055
3056 const MCExpr *ImmVal;
3057 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3058 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3059 Error(getLoc(), "index must be absent or #0");
3060 return MatchOperand_ParseFail;
3061 }
3062
3063 Operands.push_back(
3064 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3065 return MatchOperand_Success;
3066}
3067
3068/// parseOperand - Parse a arm instruction operand. For now this parses the
3069/// operand regardless of the mnemonic.
3070bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3071 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003072 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003073 // Check if the current operand has a custom associated parser, if so, try to
3074 // custom parse the operand, or fallback to the general approach.
3075 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3076 if (ResTy == MatchOperand_Success)
3077 return false;
3078 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3079 // there was a match, but an error occurred, in which case, just return that
3080 // the operand parsing failed.
3081 if (ResTy == MatchOperand_ParseFail)
3082 return true;
3083
3084 // Nothing custom, so do general case parsing.
3085 SMLoc S, E;
3086 switch (getLexer().getKind()) {
3087 default: {
3088 SMLoc S = getLoc();
3089 const MCExpr *Expr;
3090 if (parseSymbolicImmVal(Expr))
3091 return Error(S, "invalid operand");
3092
3093 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3094 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3095 return false;
3096 }
3097 case AsmToken::LBrac: {
3098 SMLoc Loc = Parser.getTok().getLoc();
3099 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3100 getContext()));
3101 Parser.Lex(); // Eat '['
3102
3103 // There's no comma after a '[', so we can parse the next operand
3104 // immediately.
3105 return parseOperand(Operands, false, false);
3106 }
3107 case AsmToken::LCurly:
3108 return parseVectorList(Operands);
3109 case AsmToken::Identifier: {
3110 // If we're expecting a Condition Code operand, then just parse that.
3111 if (isCondCode)
3112 return parseCondCode(Operands, invertCondCode);
3113
3114 // If it's a register name, parse it.
3115 if (!parseRegister(Operands))
3116 return false;
3117
3118 // This could be an optional "shift" or "extend" operand.
3119 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3120 // We can only continue if no tokens were eaten.
3121 if (GotShift != MatchOperand_NoMatch)
3122 return GotShift;
3123
3124 // This was not a register so parse other operands that start with an
3125 // identifier (like labels) as expressions and create them as immediates.
3126 const MCExpr *IdVal;
3127 S = getLoc();
3128 if (getParser().parseExpression(IdVal))
3129 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003130 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3131 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3132 return false;
3133 }
3134 case AsmToken::Integer:
3135 case AsmToken::Real:
3136 case AsmToken::Hash: {
3137 // #42 -> immediate.
3138 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003139
3140 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003141
3142 // Parse a negative sign
3143 bool isNegative = false;
3144 if (Parser.getTok().is(AsmToken::Minus)) {
3145 isNegative = true;
3146 // We need to consume this token only when we have a Real, otherwise
3147 // we let parseSymbolicImmVal take care of it
3148 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3149 Parser.Lex();
3150 }
3151
3152 // The only Real that should come through here is a literal #0.0 for
3153 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3154 // so convert the value.
3155 const AsmToken &Tok = Parser.getTok();
3156 if (Tok.is(AsmToken::Real)) {
3157 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3158 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3159 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3160 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3161 Mnemonic != "fcmlt")
3162 return TokError("unexpected floating point literal");
3163 else if (IntVal != 0 || isNegative)
3164 return TokError("expected floating-point constant #0.0");
3165 Parser.Lex(); // Eat the token.
3166
3167 Operands.push_back(
3168 AArch64Operand::CreateToken("#0", false, S, getContext()));
3169 Operands.push_back(
3170 AArch64Operand::CreateToken(".0", false, S, getContext()));
3171 return false;
3172 }
3173
3174 const MCExpr *ImmVal;
3175 if (parseSymbolicImmVal(ImmVal))
3176 return true;
3177
3178 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3179 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3180 return false;
3181 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003182 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003183 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003184 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003185 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003186 Parser.Lex(); // Eat '='
3187 const MCExpr *SubExprVal;
3188 if (getParser().parseExpression(SubExprVal))
3189 return true;
3190
David Peixottoae5ba762014-07-18 16:05:14 +00003191 if (Operands.size() < 2 ||
3192 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003193 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003194
3195 bool IsXReg =
3196 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3197 Operands[1]->getReg());
3198
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003199 MCContext& Ctx = getContext();
3200 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3201 // 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 +00003202 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003203 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3204 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3205 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3206 ShiftAmt += 16;
3207 Imm >>= 16;
3208 }
3209 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3210 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3211 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003212 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003213 if (ShiftAmt)
3214 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3215 ShiftAmt, true, S, E, Ctx));
3216 return false;
3217 }
David Peixottoae5ba762014-07-18 16:05:14 +00003218 APInt Simm = APInt(64, Imm << ShiftAmt);
3219 // check if the immediate is an unsigned or signed 32-bit int for W regs
3220 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3221 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003222 }
3223 // 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 +00003224 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003225 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003226 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3227 return false;
3228 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003229 }
3230}
3231
3232/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3233/// operands.
3234bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3235 StringRef Name, SMLoc NameLoc,
3236 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003237 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003238 Name = StringSwitch<StringRef>(Name.lower())
3239 .Case("beq", "b.eq")
3240 .Case("bne", "b.ne")
3241 .Case("bhs", "b.hs")
3242 .Case("bcs", "b.cs")
3243 .Case("blo", "b.lo")
3244 .Case("bcc", "b.cc")
3245 .Case("bmi", "b.mi")
3246 .Case("bpl", "b.pl")
3247 .Case("bvs", "b.vs")
3248 .Case("bvc", "b.vc")
3249 .Case("bhi", "b.hi")
3250 .Case("bls", "b.ls")
3251 .Case("bge", "b.ge")
3252 .Case("blt", "b.lt")
3253 .Case("bgt", "b.gt")
3254 .Case("ble", "b.le")
3255 .Case("bal", "b.al")
3256 .Case("bnv", "b.nv")
3257 .Default(Name);
3258
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003259 // First check for the AArch64-specific .req directive.
3260 if (Parser.getTok().is(AsmToken::Identifier) &&
3261 Parser.getTok().getIdentifier() == ".req") {
3262 parseDirectiveReq(Name, NameLoc);
3263 // We always return 'error' for this, as we're done with this
3264 // statement and don't need to match the 'instruction."
3265 return true;
3266 }
3267
Tim Northover3b0846e2014-05-24 12:50:23 +00003268 // Create the leading tokens for the mnemonic, split by '.' characters.
3269 size_t Start = 0, Next = Name.find('.');
3270 StringRef Head = Name.slice(Start, Next);
3271
3272 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003273 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3274 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003275
3276 Operands.push_back(
3277 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3278 Mnemonic = Head;
3279
3280 // Handle condition codes for a branch mnemonic
3281 if (Head == "b" && Next != StringRef::npos) {
3282 Start = Next;
3283 Next = Name.find('.', Start + 1);
3284 Head = Name.slice(Start + 1, Next);
3285
3286 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3287 (Head.data() - Name.data()));
3288 AArch64CC::CondCode CC = parseCondCodeString(Head);
3289 if (CC == AArch64CC::Invalid)
3290 return Error(SuffixLoc, "invalid condition code");
3291 Operands.push_back(
3292 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3293 Operands.push_back(
3294 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3295 }
3296
3297 // Add the remaining tokens in the mnemonic.
3298 while (Next != StringRef::npos) {
3299 Start = Next;
3300 Next = Name.find('.', Start + 1);
3301 Head = Name.slice(Start, Next);
3302 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3303 (Head.data() - Name.data()) + 1);
3304 Operands.push_back(
3305 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3306 }
3307
3308 // Conditional compare instructions have a Condition Code operand, which needs
3309 // to be parsed and an immediate operand created.
3310 bool condCodeFourthOperand =
3311 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3312 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3313 Head == "csinc" || Head == "csinv" || Head == "csneg");
3314
3315 // These instructions are aliases to some of the conditional select
3316 // instructions. However, the condition code is inverted in the aliased
3317 // instruction.
3318 //
3319 // FIXME: Is this the correct way to handle these? Or should the parser
3320 // generate the aliased instructions directly?
3321 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3322 bool condCodeThirdOperand =
3323 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3324
3325 // Read the remaining operands.
3326 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3327 // Read the first operand.
3328 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003329 return true;
3330 }
3331
3332 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003333 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003334 // Parse and remember the operand.
3335 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3336 (N == 3 && condCodeThirdOperand) ||
3337 (N == 2 && condCodeSecondOperand),
3338 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003339 return true;
3340 }
3341
3342 // After successfully parsing some operands there are two special cases to
3343 // consider (i.e. notional operands not separated by commas). Both are due
3344 // to memory specifiers:
3345 // + An RBrac will end an address for load/store/prefetch
3346 // + An '!' will indicate a pre-indexed operation.
3347 //
3348 // It's someone else's responsibility to make sure these tokens are sane
3349 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003350
Nirav Davee833c6c2016-11-08 18:31:04 +00003351 SMLoc RLoc = Parser.getTok().getLoc();
3352 if (parseOptionalToken(AsmToken::RBrac))
3353 Operands.push_back(
3354 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3355 SMLoc ELoc = Parser.getTok().getLoc();
3356 if (parseOptionalToken(AsmToken::Exclaim))
3357 Operands.push_back(
3358 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003359
3360 ++N;
3361 }
3362 }
3363
Nirav Davee833c6c2016-11-08 18:31:04 +00003364 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3365 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003366
Tim Northover3b0846e2014-05-24 12:50:23 +00003367 return false;
3368}
3369
3370// FIXME: This entire function is a giant hack to provide us with decent
3371// operand range validation/diagnostics until TableGen/MC can be extended
3372// to support autogeneration of this kind of validation.
3373bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3374 SmallVectorImpl<SMLoc> &Loc) {
3375 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3376 // Check for indexed addressing modes w/ the base register being the
3377 // same as a destination/source register or pair load where
3378 // the Rt == Rt2. All of those are undefined behaviour.
3379 switch (Inst.getOpcode()) {
3380 case AArch64::LDPSWpre:
3381 case AArch64::LDPWpost:
3382 case AArch64::LDPWpre:
3383 case AArch64::LDPXpost:
3384 case AArch64::LDPXpre: {
3385 unsigned Rt = Inst.getOperand(1).getReg();
3386 unsigned Rt2 = Inst.getOperand(2).getReg();
3387 unsigned Rn = Inst.getOperand(3).getReg();
3388 if (RI->isSubRegisterEq(Rn, Rt))
3389 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3390 "is also a destination");
3391 if (RI->isSubRegisterEq(Rn, Rt2))
3392 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3393 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003394 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003395 }
3396 case AArch64::LDPDi:
3397 case AArch64::LDPQi:
3398 case AArch64::LDPSi:
3399 case AArch64::LDPSWi:
3400 case AArch64::LDPWi:
3401 case AArch64::LDPXi: {
3402 unsigned Rt = Inst.getOperand(0).getReg();
3403 unsigned Rt2 = Inst.getOperand(1).getReg();
3404 if (Rt == Rt2)
3405 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3406 break;
3407 }
3408 case AArch64::LDPDpost:
3409 case AArch64::LDPDpre:
3410 case AArch64::LDPQpost:
3411 case AArch64::LDPQpre:
3412 case AArch64::LDPSpost:
3413 case AArch64::LDPSpre:
3414 case AArch64::LDPSWpost: {
3415 unsigned Rt = Inst.getOperand(1).getReg();
3416 unsigned Rt2 = Inst.getOperand(2).getReg();
3417 if (Rt == Rt2)
3418 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3419 break;
3420 }
3421 case AArch64::STPDpost:
3422 case AArch64::STPDpre:
3423 case AArch64::STPQpost:
3424 case AArch64::STPQpre:
3425 case AArch64::STPSpost:
3426 case AArch64::STPSpre:
3427 case AArch64::STPWpost:
3428 case AArch64::STPWpre:
3429 case AArch64::STPXpost:
3430 case AArch64::STPXpre: {
3431 unsigned Rt = Inst.getOperand(1).getReg();
3432 unsigned Rt2 = Inst.getOperand(2).getReg();
3433 unsigned Rn = Inst.getOperand(3).getReg();
3434 if (RI->isSubRegisterEq(Rn, Rt))
3435 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3436 "is also a source");
3437 if (RI->isSubRegisterEq(Rn, Rt2))
3438 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3439 "is also a source");
3440 break;
3441 }
3442 case AArch64::LDRBBpre:
3443 case AArch64::LDRBpre:
3444 case AArch64::LDRHHpre:
3445 case AArch64::LDRHpre:
3446 case AArch64::LDRSBWpre:
3447 case AArch64::LDRSBXpre:
3448 case AArch64::LDRSHWpre:
3449 case AArch64::LDRSHXpre:
3450 case AArch64::LDRSWpre:
3451 case AArch64::LDRWpre:
3452 case AArch64::LDRXpre:
3453 case AArch64::LDRBBpost:
3454 case AArch64::LDRBpost:
3455 case AArch64::LDRHHpost:
3456 case AArch64::LDRHpost:
3457 case AArch64::LDRSBWpost:
3458 case AArch64::LDRSBXpost:
3459 case AArch64::LDRSHWpost:
3460 case AArch64::LDRSHXpost:
3461 case AArch64::LDRSWpost:
3462 case AArch64::LDRWpost:
3463 case AArch64::LDRXpost: {
3464 unsigned Rt = Inst.getOperand(1).getReg();
3465 unsigned Rn = Inst.getOperand(2).getReg();
3466 if (RI->isSubRegisterEq(Rn, Rt))
3467 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3468 "is also a source");
3469 break;
3470 }
3471 case AArch64::STRBBpost:
3472 case AArch64::STRBpost:
3473 case AArch64::STRHHpost:
3474 case AArch64::STRHpost:
3475 case AArch64::STRWpost:
3476 case AArch64::STRXpost:
3477 case AArch64::STRBBpre:
3478 case AArch64::STRBpre:
3479 case AArch64::STRHHpre:
3480 case AArch64::STRHpre:
3481 case AArch64::STRWpre:
3482 case AArch64::STRXpre: {
3483 unsigned Rt = Inst.getOperand(1).getReg();
3484 unsigned Rn = Inst.getOperand(2).getReg();
3485 if (RI->isSubRegisterEq(Rn, Rt))
3486 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3487 "is also a source");
3488 break;
3489 }
3490 }
3491
3492 // Now check immediate ranges. Separate from the above as there is overlap
3493 // in the instructions being checked and this keeps the nested conditionals
3494 // to a minimum.
3495 switch (Inst.getOpcode()) {
3496 case AArch64::ADDSWri:
3497 case AArch64::ADDSXri:
3498 case AArch64::ADDWri:
3499 case AArch64::ADDXri:
3500 case AArch64::SUBSWri:
3501 case AArch64::SUBSXri:
3502 case AArch64::SUBWri:
3503 case AArch64::SUBXri: {
3504 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3505 // some slight duplication here.
3506 if (Inst.getOperand(2).isExpr()) {
3507 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3508 AArch64MCExpr::VariantKind ELFRefKind;
3509 MCSymbolRefExpr::VariantKind DarwinRefKind;
3510 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003511 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3512
3513 // Only allow these with ADDXri.
3514 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3515 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3516 Inst.getOpcode() == AArch64::ADDXri)
3517 return false;
3518
3519 // Only allow these with ADDXri/ADDWri
3520 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3521 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3522 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3523 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3524 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3525 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3526 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3527 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3528 (Inst.getOpcode() == AArch64::ADDXri ||
3529 Inst.getOpcode() == AArch64::ADDWri))
3530 return false;
3531
3532 // Don't allow symbol refs in the immediate field otherwise
3533 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3534 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3535 // 'cmp w0, 'borked')
3536 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003537 }
Diana Picusc93518d2016-10-11 09:17:47 +00003538 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003539 }
3540 return false;
3541 }
3542 default:
3543 return false;
3544 }
3545}
3546
3547bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3548 switch (ErrCode) {
3549 case Match_MissingFeature:
3550 return Error(Loc,
3551 "instruction requires a CPU feature not currently enabled");
3552 case Match_InvalidOperand:
3553 return Error(Loc, "invalid operand for instruction");
3554 case Match_InvalidSuffix:
3555 return Error(Loc, "invalid type suffix for instruction");
3556 case Match_InvalidCondCode:
3557 return Error(Loc, "expected AArch64 condition code");
3558 case Match_AddSubRegExtendSmall:
3559 return Error(Loc,
3560 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3561 case Match_AddSubRegExtendLarge:
3562 return Error(Loc,
3563 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3564 case Match_AddSubSecondSource:
3565 return Error(Loc,
3566 "expected compatible register, symbol or integer in range [0, 4095]");
3567 case Match_LogicalSecondSource:
3568 return Error(Loc, "expected compatible register or logical immediate");
3569 case Match_InvalidMovImm32Shift:
3570 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3571 case Match_InvalidMovImm64Shift:
3572 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3573 case Match_AddSubRegShift32:
3574 return Error(Loc,
3575 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3576 case Match_AddSubRegShift64:
3577 return Error(Loc,
3578 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3579 case Match_InvalidFPImm:
3580 return Error(Loc,
3581 "expected compatible register or floating-point constant");
3582 case Match_InvalidMemoryIndexedSImm9:
3583 return Error(Loc, "index must be an integer in range [-256, 255].");
3584 case Match_InvalidMemoryIndexed4SImm7:
3585 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3586 case Match_InvalidMemoryIndexed8SImm7:
3587 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3588 case Match_InvalidMemoryIndexed16SImm7:
3589 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3590 case Match_InvalidMemoryWExtend8:
3591 return Error(Loc,
3592 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3593 case Match_InvalidMemoryWExtend16:
3594 return Error(Loc,
3595 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3596 case Match_InvalidMemoryWExtend32:
3597 return Error(Loc,
3598 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3599 case Match_InvalidMemoryWExtend64:
3600 return Error(Loc,
3601 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3602 case Match_InvalidMemoryWExtend128:
3603 return Error(Loc,
3604 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3605 case Match_InvalidMemoryXExtend8:
3606 return Error(Loc,
3607 "expected 'lsl' or 'sxtx' with optional shift of #0");
3608 case Match_InvalidMemoryXExtend16:
3609 return Error(Loc,
3610 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3611 case Match_InvalidMemoryXExtend32:
3612 return Error(Loc,
3613 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3614 case Match_InvalidMemoryXExtend64:
3615 return Error(Loc,
3616 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3617 case Match_InvalidMemoryXExtend128:
3618 return Error(Loc,
3619 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3620 case Match_InvalidMemoryIndexed1:
3621 return Error(Loc, "index must be an integer in range [0, 4095].");
3622 case Match_InvalidMemoryIndexed2:
3623 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3624 case Match_InvalidMemoryIndexed4:
3625 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3626 case Match_InvalidMemoryIndexed8:
3627 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3628 case Match_InvalidMemoryIndexed16:
3629 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003630 case Match_InvalidImm0_1:
3631 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003632 case Match_InvalidImm0_7:
3633 return Error(Loc, "immediate must be an integer in range [0, 7].");
3634 case Match_InvalidImm0_15:
3635 return Error(Loc, "immediate must be an integer in range [0, 15].");
3636 case Match_InvalidImm0_31:
3637 return Error(Loc, "immediate must be an integer in range [0, 31].");
3638 case Match_InvalidImm0_63:
3639 return Error(Loc, "immediate must be an integer in range [0, 63].");
3640 case Match_InvalidImm0_127:
3641 return Error(Loc, "immediate must be an integer in range [0, 127].");
3642 case Match_InvalidImm0_65535:
3643 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3644 case Match_InvalidImm1_8:
3645 return Error(Loc, "immediate must be an integer in range [1, 8].");
3646 case Match_InvalidImm1_16:
3647 return Error(Loc, "immediate must be an integer in range [1, 16].");
3648 case Match_InvalidImm1_32:
3649 return Error(Loc, "immediate must be an integer in range [1, 32].");
3650 case Match_InvalidImm1_64:
3651 return Error(Loc, "immediate must be an integer in range [1, 64].");
3652 case Match_InvalidIndex1:
3653 return Error(Loc, "expected lane specifier '[1]'");
3654 case Match_InvalidIndexB:
3655 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3656 case Match_InvalidIndexH:
3657 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3658 case Match_InvalidIndexS:
3659 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3660 case Match_InvalidIndexD:
3661 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3662 case Match_InvalidLabel:
3663 return Error(Loc, "expected label or encodable integer pc offset");
3664 case Match_MRS:
3665 return Error(Loc, "expected readable system register");
3666 case Match_MSR:
3667 return Error(Loc, "expected writable system register or pstate");
3668 case Match_MnemonicFail:
3669 return Error(Loc, "unrecognized instruction mnemonic");
3670 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003671 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003672 }
3673}
3674
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003675static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003676
3677bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3678 OperandVector &Operands,
3679 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003680 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003681 bool MatchingInlineAsm) {
3682 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003683 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3684 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003685
David Blaikie960ea3f2014-06-08 16:18:35 +00003686 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003687 unsigned NumOperands = Operands.size();
3688
3689 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003690 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3691 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3692 if (Op2.isReg() && Op3.isImm()) {
3693 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003694 if (Op3CE) {
3695 uint64_t Op3Val = Op3CE->getValue();
3696 uint64_t NewOp3Val = 0;
3697 uint64_t NewOp4Val = 0;
3698 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003699 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003700 NewOp3Val = (32 - Op3Val) & 0x1f;
3701 NewOp4Val = 31 - Op3Val;
3702 } else {
3703 NewOp3Val = (64 - Op3Val) & 0x3f;
3704 NewOp4Val = 63 - Op3Val;
3705 }
3706
Jim Grosbach13760bd2015-05-30 01:25:56 +00003707 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3708 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003709
3710 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003711 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003712 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003713 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3714 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3715 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003716 }
3717 }
Tim Northover03b99f62015-04-30 18:28:58 +00003718 } else if (NumOperands == 4 && Tok == "bfc") {
3719 // FIXME: Horrible hack to handle BFC->BFM alias.
3720 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3721 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3722 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3723
3724 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3725 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3726 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3727
3728 if (LSBCE && WidthCE) {
3729 uint64_t LSB = LSBCE->getValue();
3730 uint64_t Width = WidthCE->getValue();
3731
3732 uint64_t RegWidth = 0;
3733 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3734 Op1.getReg()))
3735 RegWidth = 64;
3736 else
3737 RegWidth = 32;
3738
3739 if (LSB >= RegWidth)
3740 return Error(LSBOp.getStartLoc(),
3741 "expected integer in range [0, 31]");
3742 if (Width < 1 || Width > RegWidth)
3743 return Error(WidthOp.getStartLoc(),
3744 "expected integer in range [1, 32]");
3745
3746 uint64_t ImmR = 0;
3747 if (RegWidth == 32)
3748 ImmR = (32 - LSB) & 0x1f;
3749 else
3750 ImmR = (64 - LSB) & 0x3f;
3751
3752 uint64_t ImmS = Width - 1;
3753
3754 if (ImmR != 0 && ImmS >= ImmR)
3755 return Error(WidthOp.getStartLoc(),
3756 "requested insert overflows register");
3757
Jim Grosbach13760bd2015-05-30 01:25:56 +00003758 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3759 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003760 Operands[0] = AArch64Operand::CreateToken(
3761 "bfm", false, Op.getStartLoc(), getContext());
3762 Operands[2] = AArch64Operand::CreateReg(
3763 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3764 SMLoc(), getContext());
3765 Operands[3] = AArch64Operand::CreateImm(
3766 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3767 Operands.emplace_back(
3768 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3769 WidthOp.getEndLoc(), getContext()));
3770 }
3771 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003772 } else if (NumOperands == 5) {
3773 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3774 // UBFIZ -> UBFM aliases.
3775 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003776 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3777 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3778 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003779
David Blaikie960ea3f2014-06-08 16:18:35 +00003780 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3781 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3782 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003783
3784 if (Op3CE && Op4CE) {
3785 uint64_t Op3Val = Op3CE->getValue();
3786 uint64_t Op4Val = Op4CE->getValue();
3787
3788 uint64_t RegWidth = 0;
3789 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003790 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003791 RegWidth = 64;
3792 else
3793 RegWidth = 32;
3794
3795 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003796 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003797 "expected integer in range [0, 31]");
3798 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003799 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003800 "expected integer in range [1, 32]");
3801
3802 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003803 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003804 NewOp3Val = (32 - Op3Val) & 0x1f;
3805 else
3806 NewOp3Val = (64 - Op3Val) & 0x3f;
3807
3808 uint64_t NewOp4Val = Op4Val - 1;
3809
3810 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003811 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003812 "requested insert overflows register");
3813
3814 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003815 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003816 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003817 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003818 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003819 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003820 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003821 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003822 if (Tok == "bfi")
3823 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003824 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003825 else if (Tok == "sbfiz")
3826 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003827 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003828 else if (Tok == "ubfiz")
3829 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003830 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003831 else
3832 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003833 }
3834 }
3835
3836 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3837 // UBFX -> UBFM aliases.
3838 } else if (NumOperands == 5 &&
3839 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003840 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3841 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3842 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003843
David Blaikie960ea3f2014-06-08 16:18:35 +00003844 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3845 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3846 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003847
3848 if (Op3CE && Op4CE) {
3849 uint64_t Op3Val = Op3CE->getValue();
3850 uint64_t Op4Val = Op4CE->getValue();
3851
3852 uint64_t RegWidth = 0;
3853 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003854 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 RegWidth = 64;
3856 else
3857 RegWidth = 32;
3858
3859 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003860 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 "expected integer in range [0, 31]");
3862 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003863 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003864 "expected integer in range [1, 32]");
3865
3866 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3867
3868 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003869 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003870 "requested extract overflows register");
3871
3872 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003873 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003874 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003875 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003876 if (Tok == "bfxil")
3877 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003878 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003879 else if (Tok == "sbfx")
3880 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003881 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003882 else if (Tok == "ubfx")
3883 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003884 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003885 else
3886 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003887 }
3888 }
3889 }
3890 }
3891 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3892 // InstAlias can't quite handle this since the reg classes aren't
3893 // subclasses.
3894 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3895 // The source register can be Wn here, but the matcher expects a
3896 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003897 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3898 if (Op.isReg()) {
3899 unsigned Reg = getXRegFromWReg(Op.getReg());
3900 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3901 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003902 }
3903 }
3904 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3905 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003906 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3907 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003908 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003909 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003910 // The source register can be Wn here, but the matcher expects a
3911 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003912 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3913 if (Op.isReg()) {
3914 unsigned Reg = getXRegFromWReg(Op.getReg());
3915 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3916 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003917 }
3918 }
3919 }
3920 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3921 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003922 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3923 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003924 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003925 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003926 // The source register can be Wn here, but the matcher expects a
3927 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003928 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3929 if (Op.isReg()) {
3930 unsigned Reg = getWRegFromXReg(Op.getReg());
3931 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3932 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003933 }
3934 }
3935 }
3936
3937 // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
3938 if (NumOperands == 3 && Tok == "fmov") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003939 AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
3940 AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
3941 if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003942 unsigned zreg =
Oliver Stannardb25914e2015-11-27 13:04:48 +00003943 !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003944 RegOp.getReg())
Tim Northover3b0846e2014-05-24 12:50:23 +00003945 ? AArch64::WZR
3946 : AArch64::XZR;
David Blaikie960ea3f2014-06-08 16:18:35 +00003947 Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
3948 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003949 }
3950 }
3951
3952 MCInst Inst;
3953 // First try to match against the secondary set of tables containing the
3954 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3955 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003956 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003957
3958 // If that fails, try against the alternate table containing long-form NEON:
3959 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003960 if (MatchResult != Match_Success) {
3961 // But first, save the short-form match result: we can use it in case the
3962 // long-form match also fails.
3963 auto ShortFormNEONErrorInfo = ErrorInfo;
3964 auto ShortFormNEONMatchResult = MatchResult;
3965
Tim Northover3b0846e2014-05-24 12:50:23 +00003966 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003967 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003968
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003969 // Now, both matches failed, and the long-form match failed on the mnemonic
3970 // suffix token operand. The short-form match failure is probably more
3971 // relevant: use it instead.
3972 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003973 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003974 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3975 MatchResult = ShortFormNEONMatchResult;
3976 ErrorInfo = ShortFormNEONErrorInfo;
3977 }
3978 }
3979
3980
Tim Northover3b0846e2014-05-24 12:50:23 +00003981 switch (MatchResult) {
3982 case Match_Success: {
3983 // Perform range checking and other semantic validations
3984 SmallVector<SMLoc, 8> OperandLocs;
3985 NumOperands = Operands.size();
3986 for (unsigned i = 1; i < NumOperands; ++i)
3987 OperandLocs.push_back(Operands[i]->getStartLoc());
3988 if (validateInstruction(Inst, OperandLocs))
3989 return true;
3990
3991 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003992 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003993 return false;
3994 }
3995 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003996 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003997 // Special case the error message for the very common case where only
3998 // a single subtarget feature is missing (neon, e.g.).
3999 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004000 uint64_t Mask = 1;
4001 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4002 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004003 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004004 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004005 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004006 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004007 }
4008 return Error(IDLoc, Msg);
4009 }
4010 case Match_MnemonicFail:
4011 return showMatchError(IDLoc, MatchResult);
4012 case Match_InvalidOperand: {
4013 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004014
Tim Northover26bb14e2014-08-18 11:49:42 +00004015 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004016 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004017 return Error(IDLoc, "too few operands for instruction",
4018 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004019
David Blaikie960ea3f2014-06-08 16:18:35 +00004020 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004021 if (ErrorLoc == SMLoc())
4022 ErrorLoc = IDLoc;
4023 }
4024 // If the match failed on a suffix token operand, tweak the diagnostic
4025 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004026 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4027 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004028 MatchResult = Match_InvalidSuffix;
4029
4030 return showMatchError(ErrorLoc, MatchResult);
4031 }
4032 case Match_InvalidMemoryIndexed1:
4033 case Match_InvalidMemoryIndexed2:
4034 case Match_InvalidMemoryIndexed4:
4035 case Match_InvalidMemoryIndexed8:
4036 case Match_InvalidMemoryIndexed16:
4037 case Match_InvalidCondCode:
4038 case Match_AddSubRegExtendSmall:
4039 case Match_AddSubRegExtendLarge:
4040 case Match_AddSubSecondSource:
4041 case Match_LogicalSecondSource:
4042 case Match_AddSubRegShift32:
4043 case Match_AddSubRegShift64:
4044 case Match_InvalidMovImm32Shift:
4045 case Match_InvalidMovImm64Shift:
4046 case Match_InvalidFPImm:
4047 case Match_InvalidMemoryWExtend8:
4048 case Match_InvalidMemoryWExtend16:
4049 case Match_InvalidMemoryWExtend32:
4050 case Match_InvalidMemoryWExtend64:
4051 case Match_InvalidMemoryWExtend128:
4052 case Match_InvalidMemoryXExtend8:
4053 case Match_InvalidMemoryXExtend16:
4054 case Match_InvalidMemoryXExtend32:
4055 case Match_InvalidMemoryXExtend64:
4056 case Match_InvalidMemoryXExtend128:
4057 case Match_InvalidMemoryIndexed4SImm7:
4058 case Match_InvalidMemoryIndexed8SImm7:
4059 case Match_InvalidMemoryIndexed16SImm7:
4060 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004061 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004062 case Match_InvalidImm0_7:
4063 case Match_InvalidImm0_15:
4064 case Match_InvalidImm0_31:
4065 case Match_InvalidImm0_63:
4066 case Match_InvalidImm0_127:
4067 case Match_InvalidImm0_65535:
4068 case Match_InvalidImm1_8:
4069 case Match_InvalidImm1_16:
4070 case Match_InvalidImm1_32:
4071 case Match_InvalidImm1_64:
4072 case Match_InvalidIndex1:
4073 case Match_InvalidIndexB:
4074 case Match_InvalidIndexH:
4075 case Match_InvalidIndexS:
4076 case Match_InvalidIndexD:
4077 case Match_InvalidLabel:
4078 case Match_MSR:
4079 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004080 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004081 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004082 // Any time we get here, there's nothing fancy to do. Just get the
4083 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004084 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004085 if (ErrorLoc == SMLoc())
4086 ErrorLoc = IDLoc;
4087 return showMatchError(ErrorLoc, MatchResult);
4088 }
4089 }
4090
4091 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004092}
4093
4094/// ParseDirective parses the arm specific directives
4095bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004096 const MCObjectFileInfo::Environment Format =
4097 getContext().getObjectFileInfo()->getObjectFileType();
4098 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4099 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004100
Tim Northover3b0846e2014-05-24 12:50:23 +00004101 StringRef IDVal = DirectiveID.getIdentifier();
4102 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004103 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004104 parseDirectiveArch(Loc);
4105 else if (IDVal == ".cpu")
4106 parseDirectiveCPU(Loc);
4107 else if (IDVal == ".hword")
4108 parseDirectiveWord(2, Loc);
4109 else if (IDVal == ".word")
4110 parseDirectiveWord(4, Loc);
4111 else if (IDVal == ".xword")
4112 parseDirectiveWord(8, Loc);
4113 else if (IDVal == ".tlsdesccall")
4114 parseDirectiveTLSDescCall(Loc);
4115 else if (IDVal == ".ltorg" || IDVal == ".pool")
4116 parseDirectiveLtorg(Loc);
4117 else if (IDVal == ".unreq")
4118 parseDirectiveUnreq(Loc);
4119 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004120 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004121 parseDirectiveInst(Loc);
4122 else
4123 return true;
4124 } else if (IDVal == MCLOHDirectiveName())
4125 parseDirectiveLOH(IDVal, Loc);
4126 else
4127 return true;
4128 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004129}
4130
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004131static const struct {
4132 const char *Name;
4133 const FeatureBitset Features;
4134} ExtensionMap[] = {
4135 { "crc", {AArch64::FeatureCRC} },
4136 { "crypto", {AArch64::FeatureCrypto} },
4137 { "fp", {AArch64::FeatureFPARMv8} },
4138 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004139 { "ras", {AArch64::FeatureRAS} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004140
4141 // FIXME: Unsupported extensions
4142 { "lse", {} },
4143 { "pan", {} },
4144 { "lor", {} },
4145 { "rdma", {} },
4146 { "profile", {} },
4147};
4148
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004149/// parseDirectiveArch
4150/// ::= .arch token
4151bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4152 SMLoc ArchLoc = getLoc();
4153
4154 StringRef Arch, ExtensionString;
4155 std::tie(Arch, ExtensionString) =
4156 getParser().parseStringToEndOfStatement().trim().split('+');
4157
4158 unsigned ID = AArch64::parseArch(Arch);
Nirav Davee833c6c2016-11-08 18:31:04 +00004159 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
4160 return Error(ArchLoc, "unknown arch name");
4161
4162 if (parseToken(AsmToken::EndOfStatement))
4163 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004164
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004165 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004166 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004167 AArch64::getArchFeatures(ID, AArch64Features);
4168 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4169 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004170
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004171 MCSubtargetInfo &STI = copySTI();
4172 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4173 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4174
4175 SmallVector<StringRef, 4> RequestedExtensions;
4176 if (!ExtensionString.empty())
4177 ExtensionString.split(RequestedExtensions, '+');
4178
4179 FeatureBitset Features = STI.getFeatureBits();
4180 for (auto Name : RequestedExtensions) {
4181 bool EnableFeature = true;
4182
4183 if (Name.startswith_lower("no")) {
4184 EnableFeature = false;
4185 Name = Name.substr(2);
4186 }
4187
4188 for (const auto &Extension : ExtensionMap) {
4189 if (Extension.Name != Name)
4190 continue;
4191
4192 if (Extension.Features.none())
4193 report_fatal_error("unsupported architectural extension: " + Name);
4194
4195 FeatureBitset ToggleFeatures = EnableFeature
4196 ? (~Features & Extension.Features)
4197 : ( Features & Extension.Features);
4198 uint64_t Features =
4199 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4200 setAvailableFeatures(Features);
4201 break;
4202 }
4203 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004204 return false;
4205}
4206
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004207/// parseDirectiveCPU
4208/// ::= .cpu id
4209bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
4210 SMLoc CPULoc = getLoc();
4211
4212 StringRef CPU, ExtensionString;
4213 std::tie(CPU, ExtensionString) =
4214 getParser().parseStringToEndOfStatement().trim().split('+');
4215
Nirav Davee833c6c2016-11-08 18:31:04 +00004216 if (parseToken(AsmToken::EndOfStatement))
4217 return true;
4218
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004219 SmallVector<StringRef, 4> RequestedExtensions;
4220 if (!ExtensionString.empty())
4221 ExtensionString.split(RequestedExtensions, '+');
4222
4223 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4224 // once that is tablegen'ed
4225 if (!getSTI().isCPUStringValid(CPU)) {
4226 Error(CPULoc, "unknown CPU name");
4227 return false;
4228 }
4229
4230 MCSubtargetInfo &STI = copySTI();
4231 STI.setDefaultFeatures(CPU, "");
4232
4233 FeatureBitset Features = STI.getFeatureBits();
4234 for (auto Name : RequestedExtensions) {
4235 bool EnableFeature = true;
4236
4237 if (Name.startswith_lower("no")) {
4238 EnableFeature = false;
4239 Name = Name.substr(2);
4240 }
4241
4242 for (const auto &Extension : ExtensionMap) {
4243 if (Extension.Name != Name)
4244 continue;
4245
4246 if (Extension.Features.none())
4247 report_fatal_error("unsupported architectural extension: " + Name);
4248
4249 FeatureBitset ToggleFeatures = EnableFeature
4250 ? (~Features & Extension.Features)
4251 : ( Features & Extension.Features);
4252 uint64_t Features =
4253 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4254 setAvailableFeatures(Features);
4255
4256 break;
4257 }
4258 }
4259 return false;
4260}
4261
Tim Northover3b0846e2014-05-24 12:50:23 +00004262/// parseDirectiveWord
4263/// ::= .word [ expression (, expression)* ]
4264bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004265 auto parseOp = [&]() -> bool {
4266 const MCExpr *Value;
4267 if (getParser().parseExpression(Value))
4268 return true;
4269 getParser().getStreamer().EmitValue(Value, Size, L);
4270 return false;
4271 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004272
Nirav Davee833c6c2016-11-08 18:31:04 +00004273 if (parseMany(parseOp))
4274 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004275 return false;
4276}
4277
Chad Rosierdcd2a302014-10-22 20:35:57 +00004278/// parseDirectiveInst
4279/// ::= .inst opcode [, ...]
4280bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004281 if (getLexer().is(AsmToken::EndOfStatement))
4282 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004283
Nirav Davee833c6c2016-11-08 18:31:04 +00004284 auto parseOp = [&]() -> bool {
4285 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004286 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004287 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4288 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004289 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004290 if (check(!Value, L, "expected constant expression"))
4291 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004292 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004293 return false;
4294 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004295
Nirav Davee833c6c2016-11-08 18:31:04 +00004296 if (parseMany(parseOp))
4297 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004298 return false;
4299}
4300
Tim Northover3b0846e2014-05-24 12:50:23 +00004301// parseDirectiveTLSDescCall:
4302// ::= .tlsdesccall symbol
4303bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4304 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004305 if (check(getParser().parseIdentifier(Name), L,
4306 "expected symbol after directive") ||
4307 parseToken(AsmToken::EndOfStatement))
4308 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004309
Jim Grosbach6f482002015-05-18 18:43:14 +00004310 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004311 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4312 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004313
4314 MCInst Inst;
4315 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004316 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004317
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004318 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004319 return false;
4320}
4321
4322/// ::= .loh <lohName | lohId> label1, ..., labelN
4323/// The number of arguments depends on the loh identifier.
4324bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004325 MCLOHType Kind;
4326 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4327 if (getParser().getTok().isNot(AsmToken::Integer))
4328 return TokError("expected an identifier or a number in directive");
4329 // We successfully get a numeric value for the identifier.
4330 // Check if it is valid.
4331 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004332 if (Id <= -1U && !isValidMCLOHType(Id))
4333 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004334 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004335 } else {
4336 StringRef Name = getTok().getIdentifier();
4337 // We successfully parse an identifier.
4338 // Check if it is a recognized one.
4339 int Id = MCLOHNameToId(Name);
4340
4341 if (Id == -1)
4342 return TokError("invalid identifier in directive");
4343 Kind = (MCLOHType)Id;
4344 }
4345 // Consume the identifier.
4346 Lex();
4347 // Get the number of arguments of this LOH.
4348 int NbArgs = MCLOHIdToNbArgs(Kind);
4349
4350 assert(NbArgs != -1 && "Invalid number of arguments");
4351
4352 SmallVector<MCSymbol *, 3> Args;
4353 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4354 StringRef Name;
4355 if (getParser().parseIdentifier(Name))
4356 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004357 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004358
4359 if (Idx + 1 == NbArgs)
4360 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004361 if (parseToken(AsmToken::Comma,
4362 "unexpected token in '" + Twine(IDVal) + "' directive"))
4363 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004364 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004365 if (parseToken(AsmToken::EndOfStatement,
4366 "unexpected token in '" + Twine(IDVal) + "' directive"))
4367 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004368
4369 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4370 return false;
4371}
4372
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004373/// parseDirectiveLtorg
4374/// ::= .ltorg | .pool
4375bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004376 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4377 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004378 getTargetStreamer().emitCurrentConstantPool();
4379 return false;
4380}
4381
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004382/// parseDirectiveReq
4383/// ::= name .req registername
4384bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004385 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004386 Parser.Lex(); // Eat the '.req' token.
4387 SMLoc SRegLoc = getLoc();
4388 unsigned RegNum = tryParseRegister();
4389 bool IsVector = false;
4390
4391 if (RegNum == static_cast<unsigned>(-1)) {
4392 StringRef Kind;
4393 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004394 if (!Kind.empty())
4395 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004396 IsVector = true;
4397 }
4398
Nirav Dave2364748a2016-09-16 18:30:20 +00004399 if (RegNum == static_cast<unsigned>(-1))
4400 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004401
4402 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004403 if (parseToken(AsmToken::EndOfStatement,
4404 "unexpected input in .req directive"))
4405 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004406
4407 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004408 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004409 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4410
Nirav Dave2364748a2016-09-16 18:30:20 +00004411 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004412}
4413
4414/// parseDirectiveUneq
4415/// ::= .unreq registername
4416bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004417 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004418 if (getTok().isNot(AsmToken::Identifier))
4419 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004420 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4421 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004422 if (parseToken(AsmToken::EndOfStatement))
4423 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004424 return false;
4425}
4426
Tim Northover3b0846e2014-05-24 12:50:23 +00004427bool
4428AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4429 AArch64MCExpr::VariantKind &ELFRefKind,
4430 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4431 int64_t &Addend) {
4432 ELFRefKind = AArch64MCExpr::VK_INVALID;
4433 DarwinRefKind = MCSymbolRefExpr::VK_None;
4434 Addend = 0;
4435
4436 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4437 ELFRefKind = AE->getKind();
4438 Expr = AE->getSubExpr();
4439 }
4440
4441 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4442 if (SE) {
4443 // It's a simple symbol reference with no addend.
4444 DarwinRefKind = SE->getKind();
4445 return true;
4446 }
4447
4448 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4449 if (!BE)
4450 return false;
4451
4452 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4453 if (!SE)
4454 return false;
4455 DarwinRefKind = SE->getKind();
4456
4457 if (BE->getOpcode() != MCBinaryExpr::Add &&
4458 BE->getOpcode() != MCBinaryExpr::Sub)
4459 return false;
4460
4461 // See if the addend is is a constant, otherwise there's more going
4462 // on here than we can deal with.
4463 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4464 if (!AddendExpr)
4465 return false;
4466
4467 Addend = AddendExpr->getValue();
4468 if (BE->getOpcode() == MCBinaryExpr::Sub)
4469 Addend = -Addend;
4470
4471 // It's some symbol reference + a constant addend, but really
4472 // shouldn't use both Darwin and ELF syntax.
4473 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4474 DarwinRefKind == MCSymbolRefExpr::VK_None;
4475}
4476
4477/// Force static initialization.
4478extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004479 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4480 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4481 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004482}
4483
4484#define GET_REGISTER_MATCHER
4485#define GET_SUBTARGET_FEATURE_NAME
4486#define GET_MATCHER_IMPLEMENTATION
4487#include "AArch64GenAsmMatcher.inc"
4488
4489// Define this matcher function after the auto-generated include so we
4490// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004491unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004492 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004493 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004494 // If the kind is a token for a literal immediate, check if our asm
4495 // operand matches. This is for InstAliases which have a fixed-value
4496 // immediate in the syntax.
4497 int64_t ExpectedVal;
4498 switch (Kind) {
4499 default:
4500 return Match_InvalidOperand;
4501 case MCK__35_0:
4502 ExpectedVal = 0;
4503 break;
4504 case MCK__35_1:
4505 ExpectedVal = 1;
4506 break;
4507 case MCK__35_12:
4508 ExpectedVal = 12;
4509 break;
4510 case MCK__35_16:
4511 ExpectedVal = 16;
4512 break;
4513 case MCK__35_2:
4514 ExpectedVal = 2;
4515 break;
4516 case MCK__35_24:
4517 ExpectedVal = 24;
4518 break;
4519 case MCK__35_3:
4520 ExpectedVal = 3;
4521 break;
4522 case MCK__35_32:
4523 ExpectedVal = 32;
4524 break;
4525 case MCK__35_4:
4526 ExpectedVal = 4;
4527 break;
4528 case MCK__35_48:
4529 ExpectedVal = 48;
4530 break;
4531 case MCK__35_6:
4532 ExpectedVal = 6;
4533 break;
4534 case MCK__35_64:
4535 ExpectedVal = 64;
4536 break;
4537 case MCK__35_8:
4538 ExpectedVal = 8;
4539 break;
4540 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004541 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004542 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004543 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004544 if (!CE)
4545 return Match_InvalidOperand;
4546 if (CE->getValue() == ExpectedVal)
4547 return Match_Success;
4548 return Match_InvalidOperand;
4549}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004550
4551
Alex Bradbury58eba092016-11-01 16:32:05 +00004552OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004553AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4554
4555 SMLoc S = getLoc();
4556
4557 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4558 Error(S, "expected register");
4559 return MatchOperand_ParseFail;
4560 }
4561
4562 int FirstReg = tryParseRegister();
4563 if (FirstReg == -1) {
4564 return MatchOperand_ParseFail;
4565 }
4566 const MCRegisterClass &WRegClass =
4567 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4568 const MCRegisterClass &XRegClass =
4569 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4570
4571 bool isXReg = XRegClass.contains(FirstReg),
4572 isWReg = WRegClass.contains(FirstReg);
4573 if (!isXReg && !isWReg) {
4574 Error(S, "expected first even register of a "
4575 "consecutive same-size even/odd register pair");
4576 return MatchOperand_ParseFail;
4577 }
4578
4579 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4580 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4581
4582 if (FirstEncoding & 0x1) {
4583 Error(S, "expected first even register of a "
4584 "consecutive same-size even/odd register pair");
4585 return MatchOperand_ParseFail;
4586 }
4587
4588 SMLoc M = getLoc();
4589 if (getParser().getTok().isNot(AsmToken::Comma)) {
4590 Error(M, "expected comma");
4591 return MatchOperand_ParseFail;
4592 }
4593 // Eat the comma
4594 getParser().Lex();
4595
4596 SMLoc E = getLoc();
4597 int SecondReg = tryParseRegister();
4598 if (SecondReg ==-1) {
4599 return MatchOperand_ParseFail;
4600 }
4601
4602 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
4603 (isXReg && !XRegClass.contains(SecondReg)) ||
4604 (isWReg && !WRegClass.contains(SecondReg))) {
4605 Error(E,"expected second odd register of a "
4606 "consecutive same-size even/odd register pair");
4607 return MatchOperand_ParseFail;
4608 }
Joel Jones504bf332016-10-24 13:37:13 +00004609
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004610 unsigned Pair = 0;
4611 if(isXReg) {
4612 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4613 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4614 } else {
4615 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4616 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4617 }
4618
4619 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4620 getContext()));
4621
4622 return MatchOperand_Success;
4623}