blob: db84afacf30e2dda1e92ffb7c4fdcc5aff18c790 [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)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002209 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 {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002235 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002236 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
Chad Rosier2ff37b82016-12-27 16:58:09 +00002409 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002410 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
Chad Rosier2ff37b82016-12-27 16:58:09 +00002416 // Make sure we do actually have a number, identifier or a parenthesized
2417 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002418 SMLoc E = Parser.getTok().getLoc();
2419 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002420 !Parser.getTok().is(AsmToken::LParen) &&
2421 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002422 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002423 return MatchOperand_ParseFail;
2424 }
2425
2426 const MCExpr *ImmVal;
2427 if (getParser().parseExpression(ImmVal))
2428 return MatchOperand_ParseFail;
2429
2430 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2431 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002432 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002433 return MatchOperand_ParseFail;
2434 }
2435
Jim Grosbach57fd2622014-09-23 22:16:02 +00002436 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002437 Operands.push_back(AArch64Operand::CreateShiftExtend(
2438 ShOp, MCE->getValue(), true, S, E, getContext()));
2439 return MatchOperand_Success;
2440}
2441
2442/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2443/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2444bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2445 OperandVector &Operands) {
2446 if (Name.find('.') != StringRef::npos)
2447 return TokError("invalid operand");
2448
2449 Mnemonic = Name;
2450 Operands.push_back(
2451 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2452
Rafael Espindola961d4692014-11-11 05:18:41 +00002453 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002454 const AsmToken &Tok = Parser.getTok();
2455 StringRef Op = Tok.getString();
2456 SMLoc S = Tok.getLoc();
2457
2458 const MCExpr *Expr = nullptr;
2459
2460#define SYS_ALIAS(op1, Cn, Cm, op2) \
2461 do { \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002462 Expr = MCConstantExpr::create(op1, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002463 Operands.push_back( \
2464 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2465 Operands.push_back( \
2466 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext())); \
2467 Operands.push_back( \
2468 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext())); \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002469 Expr = MCConstantExpr::create(op2, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002470 Operands.push_back( \
2471 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2472 } while (0)
2473
2474 if (Mnemonic == "ic") {
2475 if (!Op.compare_lower("ialluis")) {
2476 // SYS #0, C7, C1, #0
2477 SYS_ALIAS(0, 7, 1, 0);
2478 } else if (!Op.compare_lower("iallu")) {
2479 // SYS #0, C7, C5, #0
2480 SYS_ALIAS(0, 7, 5, 0);
2481 } else if (!Op.compare_lower("ivau")) {
2482 // SYS #3, C7, C5, #1
2483 SYS_ALIAS(3, 7, 5, 1);
2484 } else {
2485 return TokError("invalid operand for IC instruction");
2486 }
2487 } else if (Mnemonic == "dc") {
2488 if (!Op.compare_lower("zva")) {
2489 // SYS #3, C7, C4, #1
2490 SYS_ALIAS(3, 7, 4, 1);
2491 } else if (!Op.compare_lower("ivac")) {
2492 // SYS #3, C7, C6, #1
2493 SYS_ALIAS(0, 7, 6, 1);
2494 } else if (!Op.compare_lower("isw")) {
2495 // SYS #0, C7, C6, #2
2496 SYS_ALIAS(0, 7, 6, 2);
2497 } else if (!Op.compare_lower("cvac")) {
2498 // SYS #3, C7, C10, #1
2499 SYS_ALIAS(3, 7, 10, 1);
2500 } else if (!Op.compare_lower("csw")) {
2501 // SYS #0, C7, C10, #2
2502 SYS_ALIAS(0, 7, 10, 2);
2503 } else if (!Op.compare_lower("cvau")) {
2504 // SYS #3, C7, C11, #1
2505 SYS_ALIAS(3, 7, 11, 1);
2506 } else if (!Op.compare_lower("civac")) {
2507 // SYS #3, C7, C14, #1
2508 SYS_ALIAS(3, 7, 14, 1);
2509 } else if (!Op.compare_lower("cisw")) {
2510 // SYS #0, C7, C14, #2
2511 SYS_ALIAS(0, 7, 14, 2);
Oliver Stannard1a81cc9f2015-11-26 15:28:47 +00002512 } else if (!Op.compare_lower("cvap")) {
2513 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2514 // SYS #3, C7, C12, #1
2515 SYS_ALIAS(3, 7, 12, 1);
2516 } else {
2517 return TokError("DC CVAP requires ARMv8.2a");
2518 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002519 } else {
2520 return TokError("invalid operand for DC instruction");
2521 }
2522 } else if (Mnemonic == "at") {
2523 if (!Op.compare_lower("s1e1r")) {
2524 // SYS #0, C7, C8, #0
2525 SYS_ALIAS(0, 7, 8, 0);
2526 } else if (!Op.compare_lower("s1e2r")) {
2527 // SYS #4, C7, C8, #0
2528 SYS_ALIAS(4, 7, 8, 0);
2529 } else if (!Op.compare_lower("s1e3r")) {
2530 // SYS #6, C7, C8, #0
2531 SYS_ALIAS(6, 7, 8, 0);
2532 } else if (!Op.compare_lower("s1e1w")) {
2533 // SYS #0, C7, C8, #1
2534 SYS_ALIAS(0, 7, 8, 1);
2535 } else if (!Op.compare_lower("s1e2w")) {
2536 // SYS #4, C7, C8, #1
2537 SYS_ALIAS(4, 7, 8, 1);
2538 } else if (!Op.compare_lower("s1e3w")) {
2539 // SYS #6, C7, C8, #1
2540 SYS_ALIAS(6, 7, 8, 1);
2541 } else if (!Op.compare_lower("s1e0r")) {
2542 // SYS #0, C7, C8, #3
2543 SYS_ALIAS(0, 7, 8, 2);
2544 } else if (!Op.compare_lower("s1e0w")) {
2545 // SYS #0, C7, C8, #3
2546 SYS_ALIAS(0, 7, 8, 3);
2547 } else if (!Op.compare_lower("s12e1r")) {
2548 // SYS #4, C7, C8, #4
2549 SYS_ALIAS(4, 7, 8, 4);
2550 } else if (!Op.compare_lower("s12e1w")) {
2551 // SYS #4, C7, C8, #5
2552 SYS_ALIAS(4, 7, 8, 5);
2553 } else if (!Op.compare_lower("s12e0r")) {
2554 // SYS #4, C7, C8, #6
2555 SYS_ALIAS(4, 7, 8, 6);
2556 } else if (!Op.compare_lower("s12e0w")) {
2557 // SYS #4, C7, C8, #7
2558 SYS_ALIAS(4, 7, 8, 7);
Oliver Stannard64c167d2015-11-26 15:34:44 +00002559 } else if (!Op.compare_lower("s1e1rp")) {
2560 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2561 // SYS #0, C7, C9, #0
2562 SYS_ALIAS(0, 7, 9, 0);
2563 } else {
2564 return TokError("AT S1E1RP requires ARMv8.2a");
2565 }
2566 } else if (!Op.compare_lower("s1e1wp")) {
2567 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2568 // SYS #0, C7, C9, #1
2569 SYS_ALIAS(0, 7, 9, 1);
2570 } else {
2571 return TokError("AT S1E1WP requires ARMv8.2a");
2572 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002573 } else {
2574 return TokError("invalid operand for AT instruction");
2575 }
2576 } else if (Mnemonic == "tlbi") {
2577 if (!Op.compare_lower("vmalle1is")) {
2578 // SYS #0, C8, C3, #0
2579 SYS_ALIAS(0, 8, 3, 0);
2580 } else if (!Op.compare_lower("alle2is")) {
2581 // SYS #4, C8, C3, #0
2582 SYS_ALIAS(4, 8, 3, 0);
2583 } else if (!Op.compare_lower("alle3is")) {
2584 // SYS #6, C8, C3, #0
2585 SYS_ALIAS(6, 8, 3, 0);
2586 } else if (!Op.compare_lower("vae1is")) {
2587 // SYS #0, C8, C3, #1
2588 SYS_ALIAS(0, 8, 3, 1);
2589 } else if (!Op.compare_lower("vae2is")) {
2590 // SYS #4, C8, C3, #1
2591 SYS_ALIAS(4, 8, 3, 1);
2592 } else if (!Op.compare_lower("vae3is")) {
2593 // SYS #6, C8, C3, #1
2594 SYS_ALIAS(6, 8, 3, 1);
2595 } else if (!Op.compare_lower("aside1is")) {
2596 // SYS #0, C8, C3, #2
2597 SYS_ALIAS(0, 8, 3, 2);
2598 } else if (!Op.compare_lower("vaae1is")) {
2599 // SYS #0, C8, C3, #3
2600 SYS_ALIAS(0, 8, 3, 3);
2601 } else if (!Op.compare_lower("alle1is")) {
2602 // SYS #4, C8, C3, #4
2603 SYS_ALIAS(4, 8, 3, 4);
2604 } else if (!Op.compare_lower("vale1is")) {
2605 // SYS #0, C8, C3, #5
2606 SYS_ALIAS(0, 8, 3, 5);
2607 } else if (!Op.compare_lower("vaale1is")) {
2608 // SYS #0, C8, C3, #7
2609 SYS_ALIAS(0, 8, 3, 7);
2610 } else if (!Op.compare_lower("vmalle1")) {
2611 // SYS #0, C8, C7, #0
2612 SYS_ALIAS(0, 8, 7, 0);
2613 } else if (!Op.compare_lower("alle2")) {
2614 // SYS #4, C8, C7, #0
2615 SYS_ALIAS(4, 8, 7, 0);
2616 } else if (!Op.compare_lower("vale2is")) {
2617 // SYS #4, C8, C3, #5
2618 SYS_ALIAS(4, 8, 3, 5);
2619 } else if (!Op.compare_lower("vale3is")) {
2620 // SYS #6, C8, C3, #5
2621 SYS_ALIAS(6, 8, 3, 5);
2622 } else if (!Op.compare_lower("alle3")) {
2623 // SYS #6, C8, C7, #0
2624 SYS_ALIAS(6, 8, 7, 0);
2625 } else if (!Op.compare_lower("vae1")) {
2626 // SYS #0, C8, C7, #1
2627 SYS_ALIAS(0, 8, 7, 1);
2628 } else if (!Op.compare_lower("vae2")) {
2629 // SYS #4, C8, C7, #1
2630 SYS_ALIAS(4, 8, 7, 1);
2631 } else if (!Op.compare_lower("vae3")) {
2632 // SYS #6, C8, C7, #1
2633 SYS_ALIAS(6, 8, 7, 1);
2634 } else if (!Op.compare_lower("aside1")) {
2635 // SYS #0, C8, C7, #2
2636 SYS_ALIAS(0, 8, 7, 2);
2637 } else if (!Op.compare_lower("vaae1")) {
2638 // SYS #0, C8, C7, #3
2639 SYS_ALIAS(0, 8, 7, 3);
2640 } else if (!Op.compare_lower("alle1")) {
2641 // SYS #4, C8, C7, #4
2642 SYS_ALIAS(4, 8, 7, 4);
2643 } else if (!Op.compare_lower("vale1")) {
2644 // SYS #0, C8, C7, #5
2645 SYS_ALIAS(0, 8, 7, 5);
2646 } else if (!Op.compare_lower("vale2")) {
2647 // SYS #4, C8, C7, #5
2648 SYS_ALIAS(4, 8, 7, 5);
2649 } else if (!Op.compare_lower("vale3")) {
2650 // SYS #6, C8, C7, #5
2651 SYS_ALIAS(6, 8, 7, 5);
2652 } else if (!Op.compare_lower("vaale1")) {
2653 // SYS #0, C8, C7, #7
2654 SYS_ALIAS(0, 8, 7, 7);
2655 } else if (!Op.compare_lower("ipas2e1")) {
2656 // SYS #4, C8, C4, #1
2657 SYS_ALIAS(4, 8, 4, 1);
2658 } else if (!Op.compare_lower("ipas2le1")) {
2659 // SYS #4, C8, C4, #5
2660 SYS_ALIAS(4, 8, 4, 5);
2661 } else if (!Op.compare_lower("ipas2e1is")) {
2662 // SYS #4, C8, C4, #1
2663 SYS_ALIAS(4, 8, 0, 1);
2664 } else if (!Op.compare_lower("ipas2le1is")) {
2665 // SYS #4, C8, C4, #5
2666 SYS_ALIAS(4, 8, 0, 5);
2667 } else if (!Op.compare_lower("vmalls12e1")) {
2668 // SYS #4, C8, C7, #6
2669 SYS_ALIAS(4, 8, 7, 6);
2670 } else if (!Op.compare_lower("vmalls12e1is")) {
2671 // SYS #4, C8, C3, #6
2672 SYS_ALIAS(4, 8, 3, 6);
2673 } else {
2674 return TokError("invalid operand for TLBI instruction");
2675 }
2676 }
2677
2678#undef SYS_ALIAS
2679
2680 Parser.Lex(); // Eat operand.
2681
2682 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2683 bool HasRegister = false;
2684
2685 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002686 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002687 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2688 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002689 HasRegister = true;
2690 }
2691
Tim Northover3b0846e2014-05-24 12:50:23 +00002692 if (ExpectRegister && !HasRegister) {
2693 return TokError("specified " + Mnemonic + " op requires a register");
2694 }
2695 else if (!ExpectRegister && HasRegister) {
2696 return TokError("specified " + Mnemonic + " op does not use a register");
2697 }
2698
Nirav Davee833c6c2016-11-08 18:31:04 +00002699 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2700 return true;
2701
Tim Northover3b0846e2014-05-24 12:50:23 +00002702 return false;
2703}
2704
Alex Bradbury58eba092016-11-01 16:32:05 +00002705OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002706AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002707 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002708 const AsmToken &Tok = Parser.getTok();
2709
2710 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002711 if (parseOptionalToken(AsmToken::Hash) ||
2712 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002713 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002714 const MCExpr *ImmVal;
2715 SMLoc ExprLoc = getLoc();
2716 if (getParser().parseExpression(ImmVal))
2717 return MatchOperand_ParseFail;
2718 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2719 if (!MCE) {
2720 Error(ExprLoc, "immediate value expected for barrier operand");
2721 return MatchOperand_ParseFail;
2722 }
2723 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2724 Error(ExprLoc, "barrier operand out of range");
2725 return MatchOperand_ParseFail;
2726 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002727 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2728 Operands.push_back(AArch64Operand::CreateBarrier(
2729 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002730 return MatchOperand_Success;
2731 }
2732
2733 if (Tok.isNot(AsmToken::Identifier)) {
2734 TokError("invalid operand for instruction");
2735 return MatchOperand_ParseFail;
2736 }
2737
Tim Northovere6ae6762016-07-05 21:23:04 +00002738 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2739 if (!DB) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002740 TokError("invalid barrier option name");
2741 return MatchOperand_ParseFail;
2742 }
2743
2744 // The only valid named option for ISB is 'sy'
Tim Northovere6ae6762016-07-05 21:23:04 +00002745 if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002746 TokError("'sy' or #imm operand expected");
2747 return MatchOperand_ParseFail;
2748 }
2749
Tim Northovere6ae6762016-07-05 21:23:04 +00002750 Operands.push_back(AArch64Operand::CreateBarrier(
2751 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002752 Parser.Lex(); // Consume the option
2753
2754 return MatchOperand_Success;
2755}
2756
Alex Bradbury58eba092016-11-01 16:32:05 +00002757OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002758AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002759 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002760 const AsmToken &Tok = Parser.getTok();
2761
2762 if (Tok.isNot(AsmToken::Identifier))
2763 return MatchOperand_NoMatch;
2764
Tim Northovere6ae6762016-07-05 21:23:04 +00002765 int MRSReg, MSRReg;
2766 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2767 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2768 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2769 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2770 } else
2771 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002772
Tim Northovere6ae6762016-07-05 21:23:04 +00002773 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2774 unsigned PStateImm = -1;
2775 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2776 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002777
Tim Northovere6ae6762016-07-05 21:23:04 +00002778 Operands.push_back(
2779 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2780 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002781 Parser.Lex(); // Eat identifier
2782
2783 return MatchOperand_Success;
2784}
2785
2786/// tryParseVectorRegister - Parse a vector register operand.
2787bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002788 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002789 if (Parser.getTok().isNot(AsmToken::Identifier))
2790 return true;
2791
2792 SMLoc S = getLoc();
2793 // Check for a vector register specifier first.
2794 StringRef Kind;
2795 int64_t Reg = tryMatchVectorRegister(Kind, false);
2796 if (Reg == -1)
2797 return true;
2798 Operands.push_back(
2799 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2800 // If there was an explicit qualifier, that goes on as a literal text
2801 // operand.
2802 if (!Kind.empty())
2803 Operands.push_back(
2804 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2805
2806 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002807 SMLoc SIdx = getLoc();
2808 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002809 const MCExpr *ImmVal;
2810 if (getParser().parseExpression(ImmVal))
2811 return false;
2812 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2813 if (!MCE) {
2814 TokError("immediate value expected for vector index");
2815 return false;
2816 }
2817
2818 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002819
Nirav Davee833c6c2016-11-08 18:31:04 +00002820 if (parseToken(AsmToken::RBrac, "']' expected"))
2821 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002822
2823 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2824 E, getContext()));
2825 }
2826
2827 return false;
2828}
2829
2830/// parseRegister - Parse a non-vector register operand.
2831bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002832 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002833 SMLoc S = getLoc();
2834 // Try for a vector register.
2835 if (!tryParseVectorRegister(Operands))
2836 return false;
2837
2838 // Try for a scalar register.
2839 int64_t Reg = tryParseRegister();
2840 if (Reg == -1)
2841 return true;
2842 Operands.push_back(
2843 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2844
2845 // A small number of instructions (FMOVXDhighr, for example) have "[1]"
2846 // as a string token in the instruction itself.
Nirav Davee833c6c2016-11-08 18:31:04 +00002847 SMLoc LBracS = getLoc();
2848 const AsmToken &Tok = Parser.getTok();
2849 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002850 if (Tok.is(AsmToken::Integer)) {
2851 SMLoc IntS = getLoc();
2852 int64_t Val = Tok.getIntVal();
2853 if (Val == 1) {
2854 Parser.Lex();
Nirav Davee833c6c2016-11-08 18:31:04 +00002855 SMLoc RBracS = getLoc();
2856 if (parseOptionalToken(AsmToken::RBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002857 Operands.push_back(
2858 AArch64Operand::CreateToken("[", false, LBracS, getContext()));
2859 Operands.push_back(
2860 AArch64Operand::CreateToken("1", false, IntS, getContext()));
2861 Operands.push_back(
2862 AArch64Operand::CreateToken("]", false, RBracS, getContext()));
2863 return false;
2864 }
2865 }
2866 }
2867 }
2868
2869 return false;
2870}
2871
2872bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002873 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002874 bool HasELFModifier = false;
2875 AArch64MCExpr::VariantKind RefKind;
2876
Nirav Davee833c6c2016-11-08 18:31:04 +00002877 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002878 HasELFModifier = true;
2879
Nirav Davee833c6c2016-11-08 18:31:04 +00002880 if (Parser.getTok().isNot(AsmToken::Identifier))
2881 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002882
2883 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2884 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2885 .Case("lo12", AArch64MCExpr::VK_LO12)
2886 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2887 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2888 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2889 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2890 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2891 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2892 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2893 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2894 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2895 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2896 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2897 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2898 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2899 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2900 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2901 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2902 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2903 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2904 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2905 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2906 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2907 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2908 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2909 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2910 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2911 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2912 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2913 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2914 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2915 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2916 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2917 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2918 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2919 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2920 .Default(AArch64MCExpr::VK_INVALID);
2921
Nirav Davee833c6c2016-11-08 18:31:04 +00002922 if (RefKind == AArch64MCExpr::VK_INVALID)
2923 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002924
2925 Parser.Lex(); // Eat identifier
2926
Nirav Davee833c6c2016-11-08 18:31:04 +00002927 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002928 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002929 }
2930
2931 if (getParser().parseExpression(ImmVal))
2932 return true;
2933
2934 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002935 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002936
2937 return false;
2938}
2939
2940/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2941bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002942 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002943 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2944 SMLoc S = getLoc();
2945 Parser.Lex(); // Eat left bracket token.
2946 StringRef Kind;
2947 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2948 if (FirstReg == -1)
2949 return true;
2950 int64_t PrevReg = FirstReg;
2951 unsigned Count = 1;
2952
Nirav Davee833c6c2016-11-08 18:31:04 +00002953 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002954 SMLoc Loc = getLoc();
2955 StringRef NextKind;
2956 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2957 if (Reg == -1)
2958 return true;
2959 // Any Kind suffices must match on all regs in the list.
2960 if (Kind != NextKind)
2961 return Error(Loc, "mismatched register size suffix");
2962
2963 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2964
2965 if (Space == 0 || Space > 3) {
2966 return Error(Loc, "invalid number of vectors");
2967 }
2968
2969 Count += Space;
2970 }
2971 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002972 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002973 SMLoc Loc = getLoc();
2974 StringRef NextKind;
2975 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2976 if (Reg == -1)
2977 return true;
2978 // Any Kind suffices must match on all regs in the list.
2979 if (Kind != NextKind)
2980 return Error(Loc, "mismatched register size suffix");
2981
2982 // Registers must be incremental (with wraparound at 31)
2983 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2984 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2985 return Error(Loc, "registers must be sequential");
2986
2987 PrevReg = Reg;
2988 ++Count;
2989 }
2990 }
2991
Nirav Davee833c6c2016-11-08 18:31:04 +00002992 if (parseToken(AsmToken::RCurly, "'}' expected"))
2993 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002994
2995 if (Count > 4)
2996 return Error(S, "invalid number of vectors");
2997
2998 unsigned NumElements = 0;
2999 char ElementKind = 0;
3000 if (!Kind.empty())
3001 parseValidVectorKind(Kind, NumElements, ElementKind);
3002
3003 Operands.push_back(AArch64Operand::CreateVectorList(
3004 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
3005
3006 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00003007 SMLoc SIdx = getLoc();
3008 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00003009 const MCExpr *ImmVal;
3010 if (getParser().parseExpression(ImmVal))
3011 return false;
3012 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3013 if (!MCE) {
3014 TokError("immediate value expected for vector index");
3015 return false;
3016 }
3017
3018 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003019 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003020 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003021
3022 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3023 E, getContext()));
3024 }
3025 return false;
3026}
3027
Alex Bradbury58eba092016-11-01 16:32:05 +00003028OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003029AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003030 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003031 const AsmToken &Tok = Parser.getTok();
3032 if (!Tok.is(AsmToken::Identifier))
3033 return MatchOperand_NoMatch;
3034
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003035 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00003036
3037 MCContext &Ctx = getContext();
3038 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3039 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3040 return MatchOperand_NoMatch;
3041
3042 SMLoc S = getLoc();
3043 Parser.Lex(); // Eat register
3044
Nirav Davee833c6c2016-11-08 18:31:04 +00003045 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003046 Operands.push_back(
3047 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3048 return MatchOperand_Success;
3049 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003050
Nirav Davee833c6c2016-11-08 18:31:04 +00003051 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003052
3053 if (Parser.getTok().isNot(AsmToken::Integer)) {
3054 Error(getLoc(), "index must be absent or #0");
3055 return MatchOperand_ParseFail;
3056 }
3057
3058 const MCExpr *ImmVal;
3059 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3060 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3061 Error(getLoc(), "index must be absent or #0");
3062 return MatchOperand_ParseFail;
3063 }
3064
3065 Operands.push_back(
3066 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3067 return MatchOperand_Success;
3068}
3069
3070/// parseOperand - Parse a arm instruction operand. For now this parses the
3071/// operand regardless of the mnemonic.
3072bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3073 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003074 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003075 // Check if the current operand has a custom associated parser, if so, try to
3076 // custom parse the operand, or fallback to the general approach.
3077 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3078 if (ResTy == MatchOperand_Success)
3079 return false;
3080 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3081 // there was a match, but an error occurred, in which case, just return that
3082 // the operand parsing failed.
3083 if (ResTy == MatchOperand_ParseFail)
3084 return true;
3085
3086 // Nothing custom, so do general case parsing.
3087 SMLoc S, E;
3088 switch (getLexer().getKind()) {
3089 default: {
3090 SMLoc S = getLoc();
3091 const MCExpr *Expr;
3092 if (parseSymbolicImmVal(Expr))
3093 return Error(S, "invalid operand");
3094
3095 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3096 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3097 return false;
3098 }
3099 case AsmToken::LBrac: {
3100 SMLoc Loc = Parser.getTok().getLoc();
3101 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3102 getContext()));
3103 Parser.Lex(); // Eat '['
3104
3105 // There's no comma after a '[', so we can parse the next operand
3106 // immediately.
3107 return parseOperand(Operands, false, false);
3108 }
3109 case AsmToken::LCurly:
3110 return parseVectorList(Operands);
3111 case AsmToken::Identifier: {
3112 // If we're expecting a Condition Code operand, then just parse that.
3113 if (isCondCode)
3114 return parseCondCode(Operands, invertCondCode);
3115
3116 // If it's a register name, parse it.
3117 if (!parseRegister(Operands))
3118 return false;
3119
3120 // This could be an optional "shift" or "extend" operand.
3121 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3122 // We can only continue if no tokens were eaten.
3123 if (GotShift != MatchOperand_NoMatch)
3124 return GotShift;
3125
3126 // This was not a register so parse other operands that start with an
3127 // identifier (like labels) as expressions and create them as immediates.
3128 const MCExpr *IdVal;
3129 S = getLoc();
3130 if (getParser().parseExpression(IdVal))
3131 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003132 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3133 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3134 return false;
3135 }
3136 case AsmToken::Integer:
3137 case AsmToken::Real:
3138 case AsmToken::Hash: {
3139 // #42 -> immediate.
3140 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003141
3142 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003143
3144 // Parse a negative sign
3145 bool isNegative = false;
3146 if (Parser.getTok().is(AsmToken::Minus)) {
3147 isNegative = true;
3148 // We need to consume this token only when we have a Real, otherwise
3149 // we let parseSymbolicImmVal take care of it
3150 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3151 Parser.Lex();
3152 }
3153
3154 // The only Real that should come through here is a literal #0.0 for
3155 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3156 // so convert the value.
3157 const AsmToken &Tok = Parser.getTok();
3158 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003159 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003160 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3161 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3162 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3163 Mnemonic != "fcmlt")
3164 return TokError("unexpected floating point literal");
3165 else if (IntVal != 0 || isNegative)
3166 return TokError("expected floating-point constant #0.0");
3167 Parser.Lex(); // Eat the token.
3168
3169 Operands.push_back(
3170 AArch64Operand::CreateToken("#0", false, S, getContext()));
3171 Operands.push_back(
3172 AArch64Operand::CreateToken(".0", false, S, getContext()));
3173 return false;
3174 }
3175
3176 const MCExpr *ImmVal;
3177 if (parseSymbolicImmVal(ImmVal))
3178 return true;
3179
3180 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3181 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3182 return false;
3183 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003184 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003185 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003186 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003187 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003188 Parser.Lex(); // Eat '='
3189 const MCExpr *SubExprVal;
3190 if (getParser().parseExpression(SubExprVal))
3191 return true;
3192
David Peixottoae5ba762014-07-18 16:05:14 +00003193 if (Operands.size() < 2 ||
3194 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003195 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003196
3197 bool IsXReg =
3198 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3199 Operands[1]->getReg());
3200
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003201 MCContext& Ctx = getContext();
3202 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3203 // 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 +00003204 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003205 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3206 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3207 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3208 ShiftAmt += 16;
3209 Imm >>= 16;
3210 }
3211 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3212 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3213 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003214 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003215 if (ShiftAmt)
3216 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3217 ShiftAmt, true, S, E, Ctx));
3218 return false;
3219 }
David Peixottoae5ba762014-07-18 16:05:14 +00003220 APInt Simm = APInt(64, Imm << ShiftAmt);
3221 // check if the immediate is an unsigned or signed 32-bit int for W regs
3222 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3223 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003224 }
3225 // 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 +00003226 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003227 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003228 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3229 return false;
3230 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003231 }
3232}
3233
3234/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3235/// operands.
3236bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3237 StringRef Name, SMLoc NameLoc,
3238 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003239 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003240 Name = StringSwitch<StringRef>(Name.lower())
3241 .Case("beq", "b.eq")
3242 .Case("bne", "b.ne")
3243 .Case("bhs", "b.hs")
3244 .Case("bcs", "b.cs")
3245 .Case("blo", "b.lo")
3246 .Case("bcc", "b.cc")
3247 .Case("bmi", "b.mi")
3248 .Case("bpl", "b.pl")
3249 .Case("bvs", "b.vs")
3250 .Case("bvc", "b.vc")
3251 .Case("bhi", "b.hi")
3252 .Case("bls", "b.ls")
3253 .Case("bge", "b.ge")
3254 .Case("blt", "b.lt")
3255 .Case("bgt", "b.gt")
3256 .Case("ble", "b.le")
3257 .Case("bal", "b.al")
3258 .Case("bnv", "b.nv")
3259 .Default(Name);
3260
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003261 // First check for the AArch64-specific .req directive.
3262 if (Parser.getTok().is(AsmToken::Identifier) &&
3263 Parser.getTok().getIdentifier() == ".req") {
3264 parseDirectiveReq(Name, NameLoc);
3265 // We always return 'error' for this, as we're done with this
3266 // statement and don't need to match the 'instruction."
3267 return true;
3268 }
3269
Tim Northover3b0846e2014-05-24 12:50:23 +00003270 // Create the leading tokens for the mnemonic, split by '.' characters.
3271 size_t Start = 0, Next = Name.find('.');
3272 StringRef Head = Name.slice(Start, Next);
3273
3274 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003275 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3276 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003277
3278 Operands.push_back(
3279 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3280 Mnemonic = Head;
3281
3282 // Handle condition codes for a branch mnemonic
3283 if (Head == "b" && Next != StringRef::npos) {
3284 Start = Next;
3285 Next = Name.find('.', Start + 1);
3286 Head = Name.slice(Start + 1, Next);
3287
3288 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3289 (Head.data() - Name.data()));
3290 AArch64CC::CondCode CC = parseCondCodeString(Head);
3291 if (CC == AArch64CC::Invalid)
3292 return Error(SuffixLoc, "invalid condition code");
3293 Operands.push_back(
3294 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3295 Operands.push_back(
3296 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3297 }
3298
3299 // Add the remaining tokens in the mnemonic.
3300 while (Next != StringRef::npos) {
3301 Start = Next;
3302 Next = Name.find('.', Start + 1);
3303 Head = Name.slice(Start, Next);
3304 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3305 (Head.data() - Name.data()) + 1);
3306 Operands.push_back(
3307 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3308 }
3309
3310 // Conditional compare instructions have a Condition Code operand, which needs
3311 // to be parsed and an immediate operand created.
3312 bool condCodeFourthOperand =
3313 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3314 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3315 Head == "csinc" || Head == "csinv" || Head == "csneg");
3316
3317 // These instructions are aliases to some of the conditional select
3318 // instructions. However, the condition code is inverted in the aliased
3319 // instruction.
3320 //
3321 // FIXME: Is this the correct way to handle these? Or should the parser
3322 // generate the aliased instructions directly?
3323 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3324 bool condCodeThirdOperand =
3325 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3326
3327 // Read the remaining operands.
3328 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3329 // Read the first operand.
3330 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003331 return true;
3332 }
3333
3334 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003335 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003336 // Parse and remember the operand.
3337 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3338 (N == 3 && condCodeThirdOperand) ||
3339 (N == 2 && condCodeSecondOperand),
3340 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003341 return true;
3342 }
3343
3344 // After successfully parsing some operands there are two special cases to
3345 // consider (i.e. notional operands not separated by commas). Both are due
3346 // to memory specifiers:
3347 // + An RBrac will end an address for load/store/prefetch
3348 // + An '!' will indicate a pre-indexed operation.
3349 //
3350 // It's someone else's responsibility to make sure these tokens are sane
3351 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003352
Nirav Davee833c6c2016-11-08 18:31:04 +00003353 SMLoc RLoc = Parser.getTok().getLoc();
3354 if (parseOptionalToken(AsmToken::RBrac))
3355 Operands.push_back(
3356 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3357 SMLoc ELoc = Parser.getTok().getLoc();
3358 if (parseOptionalToken(AsmToken::Exclaim))
3359 Operands.push_back(
3360 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003361
3362 ++N;
3363 }
3364 }
3365
Nirav Davee833c6c2016-11-08 18:31:04 +00003366 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3367 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003368
Tim Northover3b0846e2014-05-24 12:50:23 +00003369 return false;
3370}
3371
3372// FIXME: This entire function is a giant hack to provide us with decent
3373// operand range validation/diagnostics until TableGen/MC can be extended
3374// to support autogeneration of this kind of validation.
3375bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3376 SmallVectorImpl<SMLoc> &Loc) {
3377 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3378 // Check for indexed addressing modes w/ the base register being the
3379 // same as a destination/source register or pair load where
3380 // the Rt == Rt2. All of those are undefined behaviour.
3381 switch (Inst.getOpcode()) {
3382 case AArch64::LDPSWpre:
3383 case AArch64::LDPWpost:
3384 case AArch64::LDPWpre:
3385 case AArch64::LDPXpost:
3386 case AArch64::LDPXpre: {
3387 unsigned Rt = Inst.getOperand(1).getReg();
3388 unsigned Rt2 = Inst.getOperand(2).getReg();
3389 unsigned Rn = Inst.getOperand(3).getReg();
3390 if (RI->isSubRegisterEq(Rn, Rt))
3391 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3392 "is also a destination");
3393 if (RI->isSubRegisterEq(Rn, Rt2))
3394 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3395 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003396 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003397 }
3398 case AArch64::LDPDi:
3399 case AArch64::LDPQi:
3400 case AArch64::LDPSi:
3401 case AArch64::LDPSWi:
3402 case AArch64::LDPWi:
3403 case AArch64::LDPXi: {
3404 unsigned Rt = Inst.getOperand(0).getReg();
3405 unsigned Rt2 = Inst.getOperand(1).getReg();
3406 if (Rt == Rt2)
3407 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3408 break;
3409 }
3410 case AArch64::LDPDpost:
3411 case AArch64::LDPDpre:
3412 case AArch64::LDPQpost:
3413 case AArch64::LDPQpre:
3414 case AArch64::LDPSpost:
3415 case AArch64::LDPSpre:
3416 case AArch64::LDPSWpost: {
3417 unsigned Rt = Inst.getOperand(1).getReg();
3418 unsigned Rt2 = Inst.getOperand(2).getReg();
3419 if (Rt == Rt2)
3420 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3421 break;
3422 }
3423 case AArch64::STPDpost:
3424 case AArch64::STPDpre:
3425 case AArch64::STPQpost:
3426 case AArch64::STPQpre:
3427 case AArch64::STPSpost:
3428 case AArch64::STPSpre:
3429 case AArch64::STPWpost:
3430 case AArch64::STPWpre:
3431 case AArch64::STPXpost:
3432 case AArch64::STPXpre: {
3433 unsigned Rt = Inst.getOperand(1).getReg();
3434 unsigned Rt2 = Inst.getOperand(2).getReg();
3435 unsigned Rn = Inst.getOperand(3).getReg();
3436 if (RI->isSubRegisterEq(Rn, Rt))
3437 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3438 "is also a source");
3439 if (RI->isSubRegisterEq(Rn, Rt2))
3440 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3441 "is also a source");
3442 break;
3443 }
3444 case AArch64::LDRBBpre:
3445 case AArch64::LDRBpre:
3446 case AArch64::LDRHHpre:
3447 case AArch64::LDRHpre:
3448 case AArch64::LDRSBWpre:
3449 case AArch64::LDRSBXpre:
3450 case AArch64::LDRSHWpre:
3451 case AArch64::LDRSHXpre:
3452 case AArch64::LDRSWpre:
3453 case AArch64::LDRWpre:
3454 case AArch64::LDRXpre:
3455 case AArch64::LDRBBpost:
3456 case AArch64::LDRBpost:
3457 case AArch64::LDRHHpost:
3458 case AArch64::LDRHpost:
3459 case AArch64::LDRSBWpost:
3460 case AArch64::LDRSBXpost:
3461 case AArch64::LDRSHWpost:
3462 case AArch64::LDRSHXpost:
3463 case AArch64::LDRSWpost:
3464 case AArch64::LDRWpost:
3465 case AArch64::LDRXpost: {
3466 unsigned Rt = Inst.getOperand(1).getReg();
3467 unsigned Rn = Inst.getOperand(2).getReg();
3468 if (RI->isSubRegisterEq(Rn, Rt))
3469 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3470 "is also a source");
3471 break;
3472 }
3473 case AArch64::STRBBpost:
3474 case AArch64::STRBpost:
3475 case AArch64::STRHHpost:
3476 case AArch64::STRHpost:
3477 case AArch64::STRWpost:
3478 case AArch64::STRXpost:
3479 case AArch64::STRBBpre:
3480 case AArch64::STRBpre:
3481 case AArch64::STRHHpre:
3482 case AArch64::STRHpre:
3483 case AArch64::STRWpre:
3484 case AArch64::STRXpre: {
3485 unsigned Rt = Inst.getOperand(1).getReg();
3486 unsigned Rn = Inst.getOperand(2).getReg();
3487 if (RI->isSubRegisterEq(Rn, Rt))
3488 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3489 "is also a source");
3490 break;
3491 }
3492 }
3493
3494 // Now check immediate ranges. Separate from the above as there is overlap
3495 // in the instructions being checked and this keeps the nested conditionals
3496 // to a minimum.
3497 switch (Inst.getOpcode()) {
3498 case AArch64::ADDSWri:
3499 case AArch64::ADDSXri:
3500 case AArch64::ADDWri:
3501 case AArch64::ADDXri:
3502 case AArch64::SUBSWri:
3503 case AArch64::SUBSXri:
3504 case AArch64::SUBWri:
3505 case AArch64::SUBXri: {
3506 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3507 // some slight duplication here.
3508 if (Inst.getOperand(2).isExpr()) {
3509 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3510 AArch64MCExpr::VariantKind ELFRefKind;
3511 MCSymbolRefExpr::VariantKind DarwinRefKind;
3512 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003513 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3514
3515 // Only allow these with ADDXri.
3516 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3517 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3518 Inst.getOpcode() == AArch64::ADDXri)
3519 return false;
3520
3521 // Only allow these with ADDXri/ADDWri
3522 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3523 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3524 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3525 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3526 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3527 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3528 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3529 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3530 (Inst.getOpcode() == AArch64::ADDXri ||
3531 Inst.getOpcode() == AArch64::ADDWri))
3532 return false;
3533
3534 // Don't allow symbol refs in the immediate field otherwise
3535 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3536 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3537 // 'cmp w0, 'borked')
3538 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003539 }
Diana Picusc93518d2016-10-11 09:17:47 +00003540 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003541 }
3542 return false;
3543 }
3544 default:
3545 return false;
3546 }
3547}
3548
3549bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3550 switch (ErrCode) {
3551 case Match_MissingFeature:
3552 return Error(Loc,
3553 "instruction requires a CPU feature not currently enabled");
3554 case Match_InvalidOperand:
3555 return Error(Loc, "invalid operand for instruction");
3556 case Match_InvalidSuffix:
3557 return Error(Loc, "invalid type suffix for instruction");
3558 case Match_InvalidCondCode:
3559 return Error(Loc, "expected AArch64 condition code");
3560 case Match_AddSubRegExtendSmall:
3561 return Error(Loc,
3562 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3563 case Match_AddSubRegExtendLarge:
3564 return Error(Loc,
3565 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3566 case Match_AddSubSecondSource:
3567 return Error(Loc,
3568 "expected compatible register, symbol or integer in range [0, 4095]");
3569 case Match_LogicalSecondSource:
3570 return Error(Loc, "expected compatible register or logical immediate");
3571 case Match_InvalidMovImm32Shift:
3572 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3573 case Match_InvalidMovImm64Shift:
3574 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3575 case Match_AddSubRegShift32:
3576 return Error(Loc,
3577 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3578 case Match_AddSubRegShift64:
3579 return Error(Loc,
3580 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3581 case Match_InvalidFPImm:
3582 return Error(Loc,
3583 "expected compatible register or floating-point constant");
3584 case Match_InvalidMemoryIndexedSImm9:
3585 return Error(Loc, "index must be an integer in range [-256, 255].");
3586 case Match_InvalidMemoryIndexed4SImm7:
3587 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3588 case Match_InvalidMemoryIndexed8SImm7:
3589 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3590 case Match_InvalidMemoryIndexed16SImm7:
3591 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3592 case Match_InvalidMemoryWExtend8:
3593 return Error(Loc,
3594 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3595 case Match_InvalidMemoryWExtend16:
3596 return Error(Loc,
3597 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3598 case Match_InvalidMemoryWExtend32:
3599 return Error(Loc,
3600 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3601 case Match_InvalidMemoryWExtend64:
3602 return Error(Loc,
3603 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3604 case Match_InvalidMemoryWExtend128:
3605 return Error(Loc,
3606 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3607 case Match_InvalidMemoryXExtend8:
3608 return Error(Loc,
3609 "expected 'lsl' or 'sxtx' with optional shift of #0");
3610 case Match_InvalidMemoryXExtend16:
3611 return Error(Loc,
3612 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3613 case Match_InvalidMemoryXExtend32:
3614 return Error(Loc,
3615 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3616 case Match_InvalidMemoryXExtend64:
3617 return Error(Loc,
3618 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3619 case Match_InvalidMemoryXExtend128:
3620 return Error(Loc,
3621 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3622 case Match_InvalidMemoryIndexed1:
3623 return Error(Loc, "index must be an integer in range [0, 4095].");
3624 case Match_InvalidMemoryIndexed2:
3625 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3626 case Match_InvalidMemoryIndexed4:
3627 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3628 case Match_InvalidMemoryIndexed8:
3629 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3630 case Match_InvalidMemoryIndexed16:
3631 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003632 case Match_InvalidImm0_1:
3633 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003634 case Match_InvalidImm0_7:
3635 return Error(Loc, "immediate must be an integer in range [0, 7].");
3636 case Match_InvalidImm0_15:
3637 return Error(Loc, "immediate must be an integer in range [0, 15].");
3638 case Match_InvalidImm0_31:
3639 return Error(Loc, "immediate must be an integer in range [0, 31].");
3640 case Match_InvalidImm0_63:
3641 return Error(Loc, "immediate must be an integer in range [0, 63].");
3642 case Match_InvalidImm0_127:
3643 return Error(Loc, "immediate must be an integer in range [0, 127].");
3644 case Match_InvalidImm0_65535:
3645 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3646 case Match_InvalidImm1_8:
3647 return Error(Loc, "immediate must be an integer in range [1, 8].");
3648 case Match_InvalidImm1_16:
3649 return Error(Loc, "immediate must be an integer in range [1, 16].");
3650 case Match_InvalidImm1_32:
3651 return Error(Loc, "immediate must be an integer in range [1, 32].");
3652 case Match_InvalidImm1_64:
3653 return Error(Loc, "immediate must be an integer in range [1, 64].");
3654 case Match_InvalidIndex1:
3655 return Error(Loc, "expected lane specifier '[1]'");
3656 case Match_InvalidIndexB:
3657 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3658 case Match_InvalidIndexH:
3659 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3660 case Match_InvalidIndexS:
3661 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3662 case Match_InvalidIndexD:
3663 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3664 case Match_InvalidLabel:
3665 return Error(Loc, "expected label or encodable integer pc offset");
3666 case Match_MRS:
3667 return Error(Loc, "expected readable system register");
3668 case Match_MSR:
3669 return Error(Loc, "expected writable system register or pstate");
3670 case Match_MnemonicFail:
3671 return Error(Loc, "unrecognized instruction mnemonic");
3672 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003673 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003674 }
3675}
3676
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003677static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003678
3679bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3680 OperandVector &Operands,
3681 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003682 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003683 bool MatchingInlineAsm) {
3684 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003685 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3686 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003687
David Blaikie960ea3f2014-06-08 16:18:35 +00003688 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003689 unsigned NumOperands = Operands.size();
3690
3691 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003692 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3693 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3694 if (Op2.isReg() && Op3.isImm()) {
3695 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003696 if (Op3CE) {
3697 uint64_t Op3Val = Op3CE->getValue();
3698 uint64_t NewOp3Val = 0;
3699 uint64_t NewOp4Val = 0;
3700 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003701 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003702 NewOp3Val = (32 - Op3Val) & 0x1f;
3703 NewOp4Val = 31 - Op3Val;
3704 } else {
3705 NewOp3Val = (64 - Op3Val) & 0x3f;
3706 NewOp4Val = 63 - Op3Val;
3707 }
3708
Jim Grosbach13760bd2015-05-30 01:25:56 +00003709 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3710 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003711
3712 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003713 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003714 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003715 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3716 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3717 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003718 }
3719 }
Tim Northover03b99f62015-04-30 18:28:58 +00003720 } else if (NumOperands == 4 && Tok == "bfc") {
3721 // FIXME: Horrible hack to handle BFC->BFM alias.
3722 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3723 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3724 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3725
3726 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3727 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3728 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3729
3730 if (LSBCE && WidthCE) {
3731 uint64_t LSB = LSBCE->getValue();
3732 uint64_t Width = WidthCE->getValue();
3733
3734 uint64_t RegWidth = 0;
3735 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3736 Op1.getReg()))
3737 RegWidth = 64;
3738 else
3739 RegWidth = 32;
3740
3741 if (LSB >= RegWidth)
3742 return Error(LSBOp.getStartLoc(),
3743 "expected integer in range [0, 31]");
3744 if (Width < 1 || Width > RegWidth)
3745 return Error(WidthOp.getStartLoc(),
3746 "expected integer in range [1, 32]");
3747
3748 uint64_t ImmR = 0;
3749 if (RegWidth == 32)
3750 ImmR = (32 - LSB) & 0x1f;
3751 else
3752 ImmR = (64 - LSB) & 0x3f;
3753
3754 uint64_t ImmS = Width - 1;
3755
3756 if (ImmR != 0 && ImmS >= ImmR)
3757 return Error(WidthOp.getStartLoc(),
3758 "requested insert overflows register");
3759
Jim Grosbach13760bd2015-05-30 01:25:56 +00003760 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3761 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003762 Operands[0] = AArch64Operand::CreateToken(
3763 "bfm", false, Op.getStartLoc(), getContext());
3764 Operands[2] = AArch64Operand::CreateReg(
3765 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3766 SMLoc(), getContext());
3767 Operands[3] = AArch64Operand::CreateImm(
3768 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3769 Operands.emplace_back(
3770 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3771 WidthOp.getEndLoc(), getContext()));
3772 }
3773 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003774 } else if (NumOperands == 5) {
3775 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3776 // UBFIZ -> UBFM aliases.
3777 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003778 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3779 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3780 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003781
David Blaikie960ea3f2014-06-08 16:18:35 +00003782 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3783 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3784 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003785
3786 if (Op3CE && Op4CE) {
3787 uint64_t Op3Val = Op3CE->getValue();
3788 uint64_t Op4Val = Op4CE->getValue();
3789
3790 uint64_t RegWidth = 0;
3791 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003792 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003793 RegWidth = 64;
3794 else
3795 RegWidth = 32;
3796
3797 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003798 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003799 "expected integer in range [0, 31]");
3800 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003801 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003802 "expected integer in range [1, 32]");
3803
3804 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003805 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003806 NewOp3Val = (32 - Op3Val) & 0x1f;
3807 else
3808 NewOp3Val = (64 - Op3Val) & 0x3f;
3809
3810 uint64_t NewOp4Val = Op4Val - 1;
3811
3812 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003813 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003814 "requested insert overflows register");
3815
3816 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003817 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003818 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003819 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003820 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003821 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003822 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003823 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003824 if (Tok == "bfi")
3825 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003826 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003827 else if (Tok == "sbfiz")
3828 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003829 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003830 else if (Tok == "ubfiz")
3831 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003832 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003833 else
3834 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003835 }
3836 }
3837
3838 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3839 // UBFX -> UBFM aliases.
3840 } else if (NumOperands == 5 &&
3841 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003842 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3843 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3844 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003845
David Blaikie960ea3f2014-06-08 16:18:35 +00003846 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3847 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3848 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003849
3850 if (Op3CE && Op4CE) {
3851 uint64_t Op3Val = Op3CE->getValue();
3852 uint64_t Op4Val = Op4CE->getValue();
3853
3854 uint64_t RegWidth = 0;
3855 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003856 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003857 RegWidth = 64;
3858 else
3859 RegWidth = 32;
3860
3861 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003862 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003863 "expected integer in range [0, 31]");
3864 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003865 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 "expected integer in range [1, 32]");
3867
3868 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3869
3870 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003871 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003872 "requested extract overflows register");
3873
3874 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003875 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003876 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003877 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003878 if (Tok == "bfxil")
3879 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003880 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003881 else if (Tok == "sbfx")
3882 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003883 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003884 else if (Tok == "ubfx")
3885 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003886 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003887 else
3888 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003889 }
3890 }
3891 }
3892 }
3893 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3894 // InstAlias can't quite handle this since the reg classes aren't
3895 // subclasses.
3896 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3897 // The source register can be Wn here, but the matcher expects a
3898 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003899 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3900 if (Op.isReg()) {
3901 unsigned Reg = getXRegFromWReg(Op.getReg());
3902 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3903 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003904 }
3905 }
3906 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3907 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003908 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3909 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003910 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003911 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 // The source register can be Wn here, but the matcher expects a
3913 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003914 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3915 if (Op.isReg()) {
3916 unsigned Reg = getXRegFromWReg(Op.getReg());
3917 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3918 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003919 }
3920 }
3921 }
3922 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3923 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003924 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3925 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003926 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003927 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003928 // The source register can be Wn here, but the matcher expects a
3929 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003930 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3931 if (Op.isReg()) {
3932 unsigned Reg = getWRegFromXReg(Op.getReg());
3933 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3934 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003935 }
3936 }
3937 }
3938
3939 // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
3940 if (NumOperands == 3 && Tok == "fmov") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003941 AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
3942 AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
3943 if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003944 unsigned zreg =
Oliver Stannardb25914e2015-11-27 13:04:48 +00003945 !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003946 RegOp.getReg())
Tim Northover3b0846e2014-05-24 12:50:23 +00003947 ? AArch64::WZR
3948 : AArch64::XZR;
David Blaikie960ea3f2014-06-08 16:18:35 +00003949 Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
3950 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003951 }
3952 }
3953
3954 MCInst Inst;
3955 // First try to match against the secondary set of tables containing the
3956 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3957 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003958 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003959
3960 // If that fails, try against the alternate table containing long-form NEON:
3961 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003962 if (MatchResult != Match_Success) {
3963 // But first, save the short-form match result: we can use it in case the
3964 // long-form match also fails.
3965 auto ShortFormNEONErrorInfo = ErrorInfo;
3966 auto ShortFormNEONMatchResult = MatchResult;
3967
Tim Northover3b0846e2014-05-24 12:50:23 +00003968 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003969 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003970
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003971 // Now, both matches failed, and the long-form match failed on the mnemonic
3972 // suffix token operand. The short-form match failure is probably more
3973 // relevant: use it instead.
3974 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003975 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003976 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3977 MatchResult = ShortFormNEONMatchResult;
3978 ErrorInfo = ShortFormNEONErrorInfo;
3979 }
3980 }
3981
3982
Tim Northover3b0846e2014-05-24 12:50:23 +00003983 switch (MatchResult) {
3984 case Match_Success: {
3985 // Perform range checking and other semantic validations
3986 SmallVector<SMLoc, 8> OperandLocs;
3987 NumOperands = Operands.size();
3988 for (unsigned i = 1; i < NumOperands; ++i)
3989 OperandLocs.push_back(Operands[i]->getStartLoc());
3990 if (validateInstruction(Inst, OperandLocs))
3991 return true;
3992
3993 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003994 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003995 return false;
3996 }
3997 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003998 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003999 // Special case the error message for the very common case where only
4000 // a single subtarget feature is missing (neon, e.g.).
4001 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004002 uint64_t Mask = 1;
4003 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4004 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004005 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004006 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004007 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004008 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 }
4010 return Error(IDLoc, Msg);
4011 }
4012 case Match_MnemonicFail:
4013 return showMatchError(IDLoc, MatchResult);
4014 case Match_InvalidOperand: {
4015 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004016
Tim Northover26bb14e2014-08-18 11:49:42 +00004017 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004018 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004019 return Error(IDLoc, "too few operands for instruction",
4020 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004021
David Blaikie960ea3f2014-06-08 16:18:35 +00004022 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004023 if (ErrorLoc == SMLoc())
4024 ErrorLoc = IDLoc;
4025 }
4026 // If the match failed on a suffix token operand, tweak the diagnostic
4027 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004028 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4029 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004030 MatchResult = Match_InvalidSuffix;
4031
4032 return showMatchError(ErrorLoc, MatchResult);
4033 }
4034 case Match_InvalidMemoryIndexed1:
4035 case Match_InvalidMemoryIndexed2:
4036 case Match_InvalidMemoryIndexed4:
4037 case Match_InvalidMemoryIndexed8:
4038 case Match_InvalidMemoryIndexed16:
4039 case Match_InvalidCondCode:
4040 case Match_AddSubRegExtendSmall:
4041 case Match_AddSubRegExtendLarge:
4042 case Match_AddSubSecondSource:
4043 case Match_LogicalSecondSource:
4044 case Match_AddSubRegShift32:
4045 case Match_AddSubRegShift64:
4046 case Match_InvalidMovImm32Shift:
4047 case Match_InvalidMovImm64Shift:
4048 case Match_InvalidFPImm:
4049 case Match_InvalidMemoryWExtend8:
4050 case Match_InvalidMemoryWExtend16:
4051 case Match_InvalidMemoryWExtend32:
4052 case Match_InvalidMemoryWExtend64:
4053 case Match_InvalidMemoryWExtend128:
4054 case Match_InvalidMemoryXExtend8:
4055 case Match_InvalidMemoryXExtend16:
4056 case Match_InvalidMemoryXExtend32:
4057 case Match_InvalidMemoryXExtend64:
4058 case Match_InvalidMemoryXExtend128:
4059 case Match_InvalidMemoryIndexed4SImm7:
4060 case Match_InvalidMemoryIndexed8SImm7:
4061 case Match_InvalidMemoryIndexed16SImm7:
4062 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004063 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004064 case Match_InvalidImm0_7:
4065 case Match_InvalidImm0_15:
4066 case Match_InvalidImm0_31:
4067 case Match_InvalidImm0_63:
4068 case Match_InvalidImm0_127:
4069 case Match_InvalidImm0_65535:
4070 case Match_InvalidImm1_8:
4071 case Match_InvalidImm1_16:
4072 case Match_InvalidImm1_32:
4073 case Match_InvalidImm1_64:
4074 case Match_InvalidIndex1:
4075 case Match_InvalidIndexB:
4076 case Match_InvalidIndexH:
4077 case Match_InvalidIndexS:
4078 case Match_InvalidIndexD:
4079 case Match_InvalidLabel:
4080 case Match_MSR:
4081 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004082 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004083 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 // Any time we get here, there's nothing fancy to do. Just get the
4085 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004086 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004087 if (ErrorLoc == SMLoc())
4088 ErrorLoc = IDLoc;
4089 return showMatchError(ErrorLoc, MatchResult);
4090 }
4091 }
4092
4093 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004094}
4095
4096/// ParseDirective parses the arm specific directives
4097bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004098 const MCObjectFileInfo::Environment Format =
4099 getContext().getObjectFileInfo()->getObjectFileType();
4100 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4101 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004102
Tim Northover3b0846e2014-05-24 12:50:23 +00004103 StringRef IDVal = DirectiveID.getIdentifier();
4104 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004105 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004106 parseDirectiveArch(Loc);
4107 else if (IDVal == ".cpu")
4108 parseDirectiveCPU(Loc);
4109 else if (IDVal == ".hword")
4110 parseDirectiveWord(2, Loc);
4111 else if (IDVal == ".word")
4112 parseDirectiveWord(4, Loc);
4113 else if (IDVal == ".xword")
4114 parseDirectiveWord(8, Loc);
4115 else if (IDVal == ".tlsdesccall")
4116 parseDirectiveTLSDescCall(Loc);
4117 else if (IDVal == ".ltorg" || IDVal == ".pool")
4118 parseDirectiveLtorg(Loc);
4119 else if (IDVal == ".unreq")
4120 parseDirectiveUnreq(Loc);
4121 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004122 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004123 parseDirectiveInst(Loc);
4124 else
4125 return true;
4126 } else if (IDVal == MCLOHDirectiveName())
4127 parseDirectiveLOH(IDVal, Loc);
4128 else
4129 return true;
4130 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004131}
4132
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004133static const struct {
4134 const char *Name;
4135 const FeatureBitset Features;
4136} ExtensionMap[] = {
4137 { "crc", {AArch64::FeatureCRC} },
4138 { "crypto", {AArch64::FeatureCrypto} },
4139 { "fp", {AArch64::FeatureFPARMv8} },
4140 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004141 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004142 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004143
4144 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004145 { "pan", {} },
4146 { "lor", {} },
4147 { "rdma", {} },
4148 { "profile", {} },
4149};
4150
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004151/// parseDirectiveArch
4152/// ::= .arch token
4153bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4154 SMLoc ArchLoc = getLoc();
4155
4156 StringRef Arch, ExtensionString;
4157 std::tie(Arch, ExtensionString) =
4158 getParser().parseStringToEndOfStatement().trim().split('+');
4159
4160 unsigned ID = AArch64::parseArch(Arch);
Nirav Davee833c6c2016-11-08 18:31:04 +00004161 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
4162 return Error(ArchLoc, "unknown arch name");
4163
4164 if (parseToken(AsmToken::EndOfStatement))
4165 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004166
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004167 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004168 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004169 AArch64::getArchFeatures(ID, AArch64Features);
4170 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4171 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004172
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004173 MCSubtargetInfo &STI = copySTI();
4174 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4175 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4176
4177 SmallVector<StringRef, 4> RequestedExtensions;
4178 if (!ExtensionString.empty())
4179 ExtensionString.split(RequestedExtensions, '+');
4180
4181 FeatureBitset Features = STI.getFeatureBits();
4182 for (auto Name : RequestedExtensions) {
4183 bool EnableFeature = true;
4184
4185 if (Name.startswith_lower("no")) {
4186 EnableFeature = false;
4187 Name = Name.substr(2);
4188 }
4189
4190 for (const auto &Extension : ExtensionMap) {
4191 if (Extension.Name != Name)
4192 continue;
4193
4194 if (Extension.Features.none())
4195 report_fatal_error("unsupported architectural extension: " + Name);
4196
4197 FeatureBitset ToggleFeatures = EnableFeature
4198 ? (~Features & Extension.Features)
4199 : ( Features & Extension.Features);
4200 uint64_t Features =
4201 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4202 setAvailableFeatures(Features);
4203 break;
4204 }
4205 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004206 return false;
4207}
4208
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004209/// parseDirectiveCPU
4210/// ::= .cpu id
4211bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
4212 SMLoc CPULoc = getLoc();
4213
4214 StringRef CPU, ExtensionString;
4215 std::tie(CPU, ExtensionString) =
4216 getParser().parseStringToEndOfStatement().trim().split('+');
4217
Nirav Davee833c6c2016-11-08 18:31:04 +00004218 if (parseToken(AsmToken::EndOfStatement))
4219 return true;
4220
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004221 SmallVector<StringRef, 4> RequestedExtensions;
4222 if (!ExtensionString.empty())
4223 ExtensionString.split(RequestedExtensions, '+');
4224
4225 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4226 // once that is tablegen'ed
4227 if (!getSTI().isCPUStringValid(CPU)) {
4228 Error(CPULoc, "unknown CPU name");
4229 return false;
4230 }
4231
4232 MCSubtargetInfo &STI = copySTI();
4233 STI.setDefaultFeatures(CPU, "");
4234
4235 FeatureBitset Features = STI.getFeatureBits();
4236 for (auto Name : RequestedExtensions) {
4237 bool EnableFeature = true;
4238
4239 if (Name.startswith_lower("no")) {
4240 EnableFeature = false;
4241 Name = Name.substr(2);
4242 }
4243
4244 for (const auto &Extension : ExtensionMap) {
4245 if (Extension.Name != Name)
4246 continue;
4247
4248 if (Extension.Features.none())
4249 report_fatal_error("unsupported architectural extension: " + Name);
4250
4251 FeatureBitset ToggleFeatures = EnableFeature
4252 ? (~Features & Extension.Features)
4253 : ( Features & Extension.Features);
4254 uint64_t Features =
4255 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4256 setAvailableFeatures(Features);
4257
4258 break;
4259 }
4260 }
4261 return false;
4262}
4263
Tim Northover3b0846e2014-05-24 12:50:23 +00004264/// parseDirectiveWord
4265/// ::= .word [ expression (, expression)* ]
4266bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004267 auto parseOp = [&]() -> bool {
4268 const MCExpr *Value;
4269 if (getParser().parseExpression(Value))
4270 return true;
4271 getParser().getStreamer().EmitValue(Value, Size, L);
4272 return false;
4273 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004274
Nirav Davee833c6c2016-11-08 18:31:04 +00004275 if (parseMany(parseOp))
4276 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004277 return false;
4278}
4279
Chad Rosierdcd2a302014-10-22 20:35:57 +00004280/// parseDirectiveInst
4281/// ::= .inst opcode [, ...]
4282bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004283 if (getLexer().is(AsmToken::EndOfStatement))
4284 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004285
Nirav Davee833c6c2016-11-08 18:31:04 +00004286 auto parseOp = [&]() -> bool {
4287 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004288 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004289 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4290 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004291 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004292 if (check(!Value, L, "expected constant expression"))
4293 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004294 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004295 return false;
4296 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004297
Nirav Davee833c6c2016-11-08 18:31:04 +00004298 if (parseMany(parseOp))
4299 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004300 return false;
4301}
4302
Tim Northover3b0846e2014-05-24 12:50:23 +00004303// parseDirectiveTLSDescCall:
4304// ::= .tlsdesccall symbol
4305bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4306 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004307 if (check(getParser().parseIdentifier(Name), L,
4308 "expected symbol after directive") ||
4309 parseToken(AsmToken::EndOfStatement))
4310 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004311
Jim Grosbach6f482002015-05-18 18:43:14 +00004312 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004313 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4314 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004315
4316 MCInst Inst;
4317 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004318 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004319
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004320 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004321 return false;
4322}
4323
4324/// ::= .loh <lohName | lohId> label1, ..., labelN
4325/// The number of arguments depends on the loh identifier.
4326bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004327 MCLOHType Kind;
4328 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4329 if (getParser().getTok().isNot(AsmToken::Integer))
4330 return TokError("expected an identifier or a number in directive");
4331 // We successfully get a numeric value for the identifier.
4332 // Check if it is valid.
4333 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004334 if (Id <= -1U && !isValidMCLOHType(Id))
4335 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004336 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004337 } else {
4338 StringRef Name = getTok().getIdentifier();
4339 // We successfully parse an identifier.
4340 // Check if it is a recognized one.
4341 int Id = MCLOHNameToId(Name);
4342
4343 if (Id == -1)
4344 return TokError("invalid identifier in directive");
4345 Kind = (MCLOHType)Id;
4346 }
4347 // Consume the identifier.
4348 Lex();
4349 // Get the number of arguments of this LOH.
4350 int NbArgs = MCLOHIdToNbArgs(Kind);
4351
4352 assert(NbArgs != -1 && "Invalid number of arguments");
4353
4354 SmallVector<MCSymbol *, 3> Args;
4355 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4356 StringRef Name;
4357 if (getParser().parseIdentifier(Name))
4358 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004359 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004360
4361 if (Idx + 1 == NbArgs)
4362 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004363 if (parseToken(AsmToken::Comma,
4364 "unexpected token in '" + Twine(IDVal) + "' directive"))
4365 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004366 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004367 if (parseToken(AsmToken::EndOfStatement,
4368 "unexpected token in '" + Twine(IDVal) + "' directive"))
4369 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004370
4371 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4372 return false;
4373}
4374
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004375/// parseDirectiveLtorg
4376/// ::= .ltorg | .pool
4377bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004378 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4379 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004380 getTargetStreamer().emitCurrentConstantPool();
4381 return false;
4382}
4383
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004384/// parseDirectiveReq
4385/// ::= name .req registername
4386bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004387 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004388 Parser.Lex(); // Eat the '.req' token.
4389 SMLoc SRegLoc = getLoc();
4390 unsigned RegNum = tryParseRegister();
4391 bool IsVector = false;
4392
4393 if (RegNum == static_cast<unsigned>(-1)) {
4394 StringRef Kind;
4395 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004396 if (!Kind.empty())
4397 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004398 IsVector = true;
4399 }
4400
Nirav Dave2364748a2016-09-16 18:30:20 +00004401 if (RegNum == static_cast<unsigned>(-1))
4402 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004403
4404 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004405 if (parseToken(AsmToken::EndOfStatement,
4406 "unexpected input in .req directive"))
4407 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004408
4409 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004410 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004411 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4412
Nirav Dave2364748a2016-09-16 18:30:20 +00004413 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004414}
4415
4416/// parseDirectiveUneq
4417/// ::= .unreq registername
4418bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004419 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004420 if (getTok().isNot(AsmToken::Identifier))
4421 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004422 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4423 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004424 if (parseToken(AsmToken::EndOfStatement))
4425 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004426 return false;
4427}
4428
Tim Northover3b0846e2014-05-24 12:50:23 +00004429bool
4430AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4431 AArch64MCExpr::VariantKind &ELFRefKind,
4432 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4433 int64_t &Addend) {
4434 ELFRefKind = AArch64MCExpr::VK_INVALID;
4435 DarwinRefKind = MCSymbolRefExpr::VK_None;
4436 Addend = 0;
4437
4438 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4439 ELFRefKind = AE->getKind();
4440 Expr = AE->getSubExpr();
4441 }
4442
4443 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4444 if (SE) {
4445 // It's a simple symbol reference with no addend.
4446 DarwinRefKind = SE->getKind();
4447 return true;
4448 }
4449
4450 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4451 if (!BE)
4452 return false;
4453
4454 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4455 if (!SE)
4456 return false;
4457 DarwinRefKind = SE->getKind();
4458
4459 if (BE->getOpcode() != MCBinaryExpr::Add &&
4460 BE->getOpcode() != MCBinaryExpr::Sub)
4461 return false;
4462
4463 // See if the addend is is a constant, otherwise there's more going
4464 // on here than we can deal with.
4465 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4466 if (!AddendExpr)
4467 return false;
4468
4469 Addend = AddendExpr->getValue();
4470 if (BE->getOpcode() == MCBinaryExpr::Sub)
4471 Addend = -Addend;
4472
4473 // It's some symbol reference + a constant addend, but really
4474 // shouldn't use both Darwin and ELF syntax.
4475 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4476 DarwinRefKind == MCSymbolRefExpr::VK_None;
4477}
4478
4479/// Force static initialization.
4480extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004481 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4482 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4483 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004484}
4485
4486#define GET_REGISTER_MATCHER
4487#define GET_SUBTARGET_FEATURE_NAME
4488#define GET_MATCHER_IMPLEMENTATION
4489#include "AArch64GenAsmMatcher.inc"
4490
4491// Define this matcher function after the auto-generated include so we
4492// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004493unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004494 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004495 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004496 // If the kind is a token for a literal immediate, check if our asm
4497 // operand matches. This is for InstAliases which have a fixed-value
4498 // immediate in the syntax.
4499 int64_t ExpectedVal;
4500 switch (Kind) {
4501 default:
4502 return Match_InvalidOperand;
4503 case MCK__35_0:
4504 ExpectedVal = 0;
4505 break;
4506 case MCK__35_1:
4507 ExpectedVal = 1;
4508 break;
4509 case MCK__35_12:
4510 ExpectedVal = 12;
4511 break;
4512 case MCK__35_16:
4513 ExpectedVal = 16;
4514 break;
4515 case MCK__35_2:
4516 ExpectedVal = 2;
4517 break;
4518 case MCK__35_24:
4519 ExpectedVal = 24;
4520 break;
4521 case MCK__35_3:
4522 ExpectedVal = 3;
4523 break;
4524 case MCK__35_32:
4525 ExpectedVal = 32;
4526 break;
4527 case MCK__35_4:
4528 ExpectedVal = 4;
4529 break;
4530 case MCK__35_48:
4531 ExpectedVal = 48;
4532 break;
4533 case MCK__35_6:
4534 ExpectedVal = 6;
4535 break;
4536 case MCK__35_64:
4537 ExpectedVal = 64;
4538 break;
4539 case MCK__35_8:
4540 ExpectedVal = 8;
4541 break;
4542 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004543 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004544 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004546 if (!CE)
4547 return Match_InvalidOperand;
4548 if (CE->getValue() == ExpectedVal)
4549 return Match_Success;
4550 return Match_InvalidOperand;
4551}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004552
4553
Alex Bradbury58eba092016-11-01 16:32:05 +00004554OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004555AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4556
4557 SMLoc S = getLoc();
4558
4559 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4560 Error(S, "expected register");
4561 return MatchOperand_ParseFail;
4562 }
4563
4564 int FirstReg = tryParseRegister();
4565 if (FirstReg == -1) {
4566 return MatchOperand_ParseFail;
4567 }
4568 const MCRegisterClass &WRegClass =
4569 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4570 const MCRegisterClass &XRegClass =
4571 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4572
4573 bool isXReg = XRegClass.contains(FirstReg),
4574 isWReg = WRegClass.contains(FirstReg);
4575 if (!isXReg && !isWReg) {
4576 Error(S, "expected first even register of a "
4577 "consecutive same-size even/odd register pair");
4578 return MatchOperand_ParseFail;
4579 }
4580
4581 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4582 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4583
4584 if (FirstEncoding & 0x1) {
4585 Error(S, "expected first even register of a "
4586 "consecutive same-size even/odd register pair");
4587 return MatchOperand_ParseFail;
4588 }
4589
4590 SMLoc M = getLoc();
4591 if (getParser().getTok().isNot(AsmToken::Comma)) {
4592 Error(M, "expected comma");
4593 return MatchOperand_ParseFail;
4594 }
4595 // Eat the comma
4596 getParser().Lex();
4597
4598 SMLoc E = getLoc();
4599 int SecondReg = tryParseRegister();
4600 if (SecondReg ==-1) {
4601 return MatchOperand_ParseFail;
4602 }
4603
4604 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
4605 (isXReg && !XRegClass.contains(SecondReg)) ||
4606 (isWReg && !WRegClass.contains(SecondReg))) {
4607 Error(E,"expected second odd register of a "
4608 "consecutive same-size even/odd register pair");
4609 return MatchOperand_ParseFail;
4610 }
Joel Jones504bf332016-10-24 13:37:13 +00004611
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004612 unsigned Pair = 0;
4613 if(isXReg) {
4614 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4615 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4616 } else {
4617 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4618 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4619 }
4620
4621 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4622 getContext()));
4623
4624 return MatchOperand_Success;
4625}