blob: 2edacdba4b2825a9f6debaf9b55eb83489c0f0a3 [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
Rafael Espindola961d4692014-11-11 05:18:41 +000071 void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); }
72 bool Error(SMLoc L, const Twine &Msg) { return getParser().Error(L, Msg); }
Tim Northover3b0846e2014-05-24 12:50:23 +000073 bool showMatchError(SMLoc Loc, unsigned ErrCode);
74
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000075 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000076 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000077 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000078 bool parseDirectiveInst(SMLoc L);
79
Tim Northover3b0846e2014-05-24 12:50:23 +000080 bool parseDirectiveTLSDescCall(SMLoc L);
81
82 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000083 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000084
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000085 bool parseDirectiveReq(StringRef Name, SMLoc L);
86 bool parseDirectiveUnreq(SMLoc L);
87
Tim Northover3b0846e2014-05-24 12:50:23 +000088 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
89 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
90 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +000091 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool MatchingInlineAsm) override;
93/// @name Auto-generated Match Functions
94/// {
95
96#define GET_ASSEMBLER_HEADER
97#include "AArch64GenAsmMatcher.inc"
98
99 /// }
100
101 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
102 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
103 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
104 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
105 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
106 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000107 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000108 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
109 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
110 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
111 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
112 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
113 bool tryParseVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000114 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000115
116public:
117 enum AArch64MatchResultTy {
118 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
119#define GET_OPERAND_DIAGNOSTIC_TYPES
120#include "AArch64GenAsmMatcher.inc"
121 };
Akira Hatanakab11ef082015-11-14 06:35:56 +0000122 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000123 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000124 : MCTargetAsmParser(Options, STI) {
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();
1973 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1974
1975 std::string lowerCase = Tok.getString().lower();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001976 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
Tim Northover3b0846e2014-05-24 12:50:23 +00001977 // Also handle a few aliases of registers.
1978 if (RegNum == 0)
1979 RegNum = StringSwitch<unsigned>(lowerCase)
1980 .Case("fp", AArch64::FP)
1981 .Case("lr", AArch64::LR)
1982 .Case("x31", AArch64::XZR)
1983 .Case("w31", AArch64::WZR)
1984 .Default(0);
1985
1986 if (RegNum == 0)
1987 return -1;
1988
1989 Parser.Lex(); // Eat identifier token.
1990 return RegNum;
1991}
1992
1993/// tryMatchVectorRegister - Try to parse a vector register name with optional
1994/// kind specifier. If it is a register specifier, eat the token and return it.
1995int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001996 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001997 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1998 TokError("vector register expected");
1999 return -1;
2000 }
2001
2002 StringRef Name = Parser.getTok().getString();
2003 // If there is a kind specifier, it's separated from the register name by
2004 // a '.'.
2005 size_t Start = 0, Next = Name.find('.');
2006 StringRef Head = Name.slice(Start, Next);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002007 unsigned RegNum = matchRegisterNameAlias(Head, true);
2008
Tim Northover3b0846e2014-05-24 12:50:23 +00002009 if (RegNum) {
2010 if (Next != StringRef::npos) {
2011 Kind = Name.slice(Next, StringRef::npos);
2012 if (!isValidVectorKind(Kind)) {
2013 TokError("invalid vector kind qualifier");
2014 return -1;
2015 }
2016 }
2017 Parser.Lex(); // Eat the register token.
2018 return RegNum;
2019 }
2020
2021 if (expected)
2022 TokError("vector register expected");
2023 return -1;
2024}
2025
2026/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
2027AArch64AsmParser::OperandMatchResultTy
2028AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002029 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002030 SMLoc S = getLoc();
2031
2032 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2033 Error(S, "Expected cN operand where 0 <= N <= 15");
2034 return MatchOperand_ParseFail;
2035 }
2036
2037 StringRef Tok = Parser.getTok().getIdentifier();
2038 if (Tok[0] != 'c' && Tok[0] != 'C') {
2039 Error(S, "Expected cN operand where 0 <= N <= 15");
2040 return MatchOperand_ParseFail;
2041 }
2042
2043 uint32_t CRNum;
2044 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2045 if (BadNum || CRNum > 15) {
2046 Error(S, "Expected cN operand where 0 <= N <= 15");
2047 return MatchOperand_ParseFail;
2048 }
2049
2050 Parser.Lex(); // Eat identifier token.
2051 Operands.push_back(
2052 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2053 return MatchOperand_Success;
2054}
2055
2056/// tryParsePrefetch - Try to parse a prefetch operand.
2057AArch64AsmParser::OperandMatchResultTy
2058AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002059 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002060 SMLoc S = getLoc();
2061 const AsmToken &Tok = Parser.getTok();
2062 // Either an identifier for named values or a 5-bit immediate.
2063 bool Hash = Tok.is(AsmToken::Hash);
2064 if (Hash || Tok.is(AsmToken::Integer)) {
2065 if (Hash)
2066 Parser.Lex(); // Eat hash token.
2067 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
2106AArch64AsmParser::OperandMatchResultTy
2107AArch64AsmParser::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.
2130AArch64AsmParser::OperandMatchResultTy
2131AArch64AsmParser::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.
2181AArch64AsmParser::OperandMatchResultTy
2182AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002183 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002184 SMLoc S = getLoc();
2185 const MCExpr *Expr;
2186
2187 if (Parser.getTok().is(AsmToken::Hash)) {
2188 Parser.Lex(); // Eat hash token.
2189 }
2190
2191 if (getParser().parseExpression(Expr))
2192 return MatchOperand_ParseFail;
2193
2194 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2195 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2196
2197 return MatchOperand_Success;
2198}
2199
2200/// tryParseFPImm - A floating point immediate expression operand.
2201AArch64AsmParser::OperandMatchResultTy
2202AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002203 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002204 SMLoc S = getLoc();
2205
2206 bool Hash = false;
2207 if (Parser.getTok().is(AsmToken::Hash)) {
2208 Parser.Lex(); // Eat '#'
2209 Hash = true;
2210 }
2211
2212 // Handle negation, as that still comes through as a separate token.
2213 bool isNegative = false;
2214 if (Parser.getTok().is(AsmToken::Minus)) {
2215 isNegative = true;
2216 Parser.Lex();
2217 }
2218 const AsmToken &Tok = Parser.getTok();
2219 if (Tok.is(AsmToken::Real)) {
2220 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002221 if (isNegative)
2222 RealVal.changeSign();
2223
Tim Northover3b0846e2014-05-24 12:50:23 +00002224 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002225 int Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2226 Parser.Lex(); // Eat the token.
2227 // Check for out of range values. As an exception, we let Zero through,
2228 // as we handle that special case in post-processing before matching in
2229 // order to use the zero register for it.
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002230 if (Val == -1 && !RealVal.isPosZero()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002231 TokError("expected compatible register or floating-point constant");
2232 return MatchOperand_ParseFail;
2233 }
2234 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2235 return MatchOperand_Success;
2236 }
2237 if (Tok.is(AsmToken::Integer)) {
2238 int64_t Val;
2239 if (!isNegative && Tok.getString().startswith("0x")) {
2240 Val = Tok.getIntVal();
2241 if (Val > 255 || Val < 0) {
2242 TokError("encoded floating point value out of range");
2243 return MatchOperand_ParseFail;
2244 }
2245 } else {
2246 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
2247 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2248 // If we had a '-' in front, toggle the sign bit.
2249 IntVal ^= (uint64_t)isNegative << 63;
2250 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2251 }
2252 Parser.Lex(); // Eat the token.
2253 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2254 return MatchOperand_Success;
2255 }
2256
2257 if (!Hash)
2258 return MatchOperand_NoMatch;
2259
2260 TokError("invalid floating point immediate");
2261 return MatchOperand_ParseFail;
2262}
2263
2264/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
2265AArch64AsmParser::OperandMatchResultTy
2266AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002267 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002268 SMLoc S = getLoc();
2269
2270 if (Parser.getTok().is(AsmToken::Hash))
2271 Parser.Lex(); // Eat '#'
2272 else if (Parser.getTok().isNot(AsmToken::Integer))
2273 // Operand should start from # or should be integer, emit error otherwise.
2274 return MatchOperand_NoMatch;
2275
2276 const MCExpr *Imm;
2277 if (parseSymbolicImmVal(Imm))
2278 return MatchOperand_ParseFail;
2279 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2280 uint64_t ShiftAmount = 0;
2281 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2282 if (MCE) {
2283 int64_t Val = MCE->getValue();
2284 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002285 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002286 ShiftAmount = 12;
2287 }
2288 }
2289 SMLoc E = Parser.getTok().getLoc();
2290 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2291 getContext()));
2292 return MatchOperand_Success;
2293 }
2294
2295 // Eat ','
2296 Parser.Lex();
2297
2298 // The optional operand must be "lsl #N" where N is non-negative.
2299 if (!Parser.getTok().is(AsmToken::Identifier) ||
2300 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2301 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2302 return MatchOperand_ParseFail;
2303 }
2304
2305 // Eat 'lsl'
2306 Parser.Lex();
2307
2308 if (Parser.getTok().is(AsmToken::Hash)) {
2309 Parser.Lex();
2310 }
2311
2312 if (Parser.getTok().isNot(AsmToken::Integer)) {
2313 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2314 return MatchOperand_ParseFail;
2315 }
2316
2317 int64_t ShiftAmount = Parser.getTok().getIntVal();
2318
2319 if (ShiftAmount < 0) {
2320 Error(Parser.getTok().getLoc(), "positive shift amount required");
2321 return MatchOperand_ParseFail;
2322 }
2323 Parser.Lex(); // Eat the number
2324
2325 SMLoc E = Parser.getTok().getLoc();
2326 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2327 S, E, getContext()));
2328 return MatchOperand_Success;
2329}
2330
2331/// parseCondCodeString - Parse a Condition Code string.
2332AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2333 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2334 .Case("eq", AArch64CC::EQ)
2335 .Case("ne", AArch64CC::NE)
2336 .Case("cs", AArch64CC::HS)
2337 .Case("hs", AArch64CC::HS)
2338 .Case("cc", AArch64CC::LO)
2339 .Case("lo", AArch64CC::LO)
2340 .Case("mi", AArch64CC::MI)
2341 .Case("pl", AArch64CC::PL)
2342 .Case("vs", AArch64CC::VS)
2343 .Case("vc", AArch64CC::VC)
2344 .Case("hi", AArch64CC::HI)
2345 .Case("ls", AArch64CC::LS)
2346 .Case("ge", AArch64CC::GE)
2347 .Case("lt", AArch64CC::LT)
2348 .Case("gt", AArch64CC::GT)
2349 .Case("le", AArch64CC::LE)
2350 .Case("al", AArch64CC::AL)
2351 .Case("nv", AArch64CC::NV)
2352 .Default(AArch64CC::Invalid);
2353 return CC;
2354}
2355
2356/// parseCondCode - Parse a Condition Code operand.
2357bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2358 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002359 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002360 SMLoc S = getLoc();
2361 const AsmToken &Tok = Parser.getTok();
2362 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2363
2364 StringRef Cond = Tok.getString();
2365 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2366 if (CC == AArch64CC::Invalid)
2367 return TokError("invalid condition code");
2368 Parser.Lex(); // Eat identifier token.
2369
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002370 if (invertCondCode) {
2371 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2372 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002373 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002374 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002375
2376 Operands.push_back(
2377 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2378 return false;
2379}
2380
2381/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2382/// them if present.
2383AArch64AsmParser::OperandMatchResultTy
2384AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002385 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002386 const AsmToken &Tok = Parser.getTok();
2387 std::string LowerID = Tok.getString().lower();
2388 AArch64_AM::ShiftExtendType ShOp =
2389 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2390 .Case("lsl", AArch64_AM::LSL)
2391 .Case("lsr", AArch64_AM::LSR)
2392 .Case("asr", AArch64_AM::ASR)
2393 .Case("ror", AArch64_AM::ROR)
2394 .Case("msl", AArch64_AM::MSL)
2395 .Case("uxtb", AArch64_AM::UXTB)
2396 .Case("uxth", AArch64_AM::UXTH)
2397 .Case("uxtw", AArch64_AM::UXTW)
2398 .Case("uxtx", AArch64_AM::UXTX)
2399 .Case("sxtb", AArch64_AM::SXTB)
2400 .Case("sxth", AArch64_AM::SXTH)
2401 .Case("sxtw", AArch64_AM::SXTW)
2402 .Case("sxtx", AArch64_AM::SXTX)
2403 .Default(AArch64_AM::InvalidShiftExtend);
2404
2405 if (ShOp == AArch64_AM::InvalidShiftExtend)
2406 return MatchOperand_NoMatch;
2407
2408 SMLoc S = Tok.getLoc();
2409 Parser.Lex();
2410
2411 bool Hash = getLexer().is(AsmToken::Hash);
2412 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2413 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2414 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2415 ShOp == AArch64_AM::MSL) {
2416 // We expect a number here.
2417 TokError("expected #imm after shift specifier");
2418 return MatchOperand_ParseFail;
2419 }
2420
2421 // "extend" type operatoins don't need an immediate, #0 is implicit.
2422 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2423 Operands.push_back(
2424 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2425 return MatchOperand_Success;
2426 }
2427
2428 if (Hash)
2429 Parser.Lex(); // Eat the '#'.
2430
Jim Grosbach57fd2622014-09-23 22:16:02 +00002431 // Make sure we do actually have a number or a parenthesized expression.
2432 SMLoc E = Parser.getTok().getLoc();
2433 if (!Parser.getTok().is(AsmToken::Integer) &&
2434 !Parser.getTok().is(AsmToken::LParen)) {
2435 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002436 return MatchOperand_ParseFail;
2437 }
2438
2439 const MCExpr *ImmVal;
2440 if (getParser().parseExpression(ImmVal))
2441 return MatchOperand_ParseFail;
2442
2443 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2444 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002445 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002446 return MatchOperand_ParseFail;
2447 }
2448
Jim Grosbach57fd2622014-09-23 22:16:02 +00002449 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002450 Operands.push_back(AArch64Operand::CreateShiftExtend(
2451 ShOp, MCE->getValue(), true, S, E, getContext()));
2452 return MatchOperand_Success;
2453}
2454
2455/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2456/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2457bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2458 OperandVector &Operands) {
2459 if (Name.find('.') != StringRef::npos)
2460 return TokError("invalid operand");
2461
2462 Mnemonic = Name;
2463 Operands.push_back(
2464 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2465
Rafael Espindola961d4692014-11-11 05:18:41 +00002466 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002467 const AsmToken &Tok = Parser.getTok();
2468 StringRef Op = Tok.getString();
2469 SMLoc S = Tok.getLoc();
2470
2471 const MCExpr *Expr = nullptr;
2472
2473#define SYS_ALIAS(op1, Cn, Cm, op2) \
2474 do { \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002475 Expr = MCConstantExpr::create(op1, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002476 Operands.push_back( \
2477 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2478 Operands.push_back( \
2479 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext())); \
2480 Operands.push_back( \
2481 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext())); \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002482 Expr = MCConstantExpr::create(op2, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002483 Operands.push_back( \
2484 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2485 } while (0)
2486
2487 if (Mnemonic == "ic") {
2488 if (!Op.compare_lower("ialluis")) {
2489 // SYS #0, C7, C1, #0
2490 SYS_ALIAS(0, 7, 1, 0);
2491 } else if (!Op.compare_lower("iallu")) {
2492 // SYS #0, C7, C5, #0
2493 SYS_ALIAS(0, 7, 5, 0);
2494 } else if (!Op.compare_lower("ivau")) {
2495 // SYS #3, C7, C5, #1
2496 SYS_ALIAS(3, 7, 5, 1);
2497 } else {
2498 return TokError("invalid operand for IC instruction");
2499 }
2500 } else if (Mnemonic == "dc") {
2501 if (!Op.compare_lower("zva")) {
2502 // SYS #3, C7, C4, #1
2503 SYS_ALIAS(3, 7, 4, 1);
2504 } else if (!Op.compare_lower("ivac")) {
2505 // SYS #3, C7, C6, #1
2506 SYS_ALIAS(0, 7, 6, 1);
2507 } else if (!Op.compare_lower("isw")) {
2508 // SYS #0, C7, C6, #2
2509 SYS_ALIAS(0, 7, 6, 2);
2510 } else if (!Op.compare_lower("cvac")) {
2511 // SYS #3, C7, C10, #1
2512 SYS_ALIAS(3, 7, 10, 1);
2513 } else if (!Op.compare_lower("csw")) {
2514 // SYS #0, C7, C10, #2
2515 SYS_ALIAS(0, 7, 10, 2);
2516 } else if (!Op.compare_lower("cvau")) {
2517 // SYS #3, C7, C11, #1
2518 SYS_ALIAS(3, 7, 11, 1);
2519 } else if (!Op.compare_lower("civac")) {
2520 // SYS #3, C7, C14, #1
2521 SYS_ALIAS(3, 7, 14, 1);
2522 } else if (!Op.compare_lower("cisw")) {
2523 // SYS #0, C7, C14, #2
2524 SYS_ALIAS(0, 7, 14, 2);
Oliver Stannard1a81cc9f2015-11-26 15:28:47 +00002525 } else if (!Op.compare_lower("cvap")) {
2526 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2527 // SYS #3, C7, C12, #1
2528 SYS_ALIAS(3, 7, 12, 1);
2529 } else {
2530 return TokError("DC CVAP requires ARMv8.2a");
2531 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002532 } else {
2533 return TokError("invalid operand for DC instruction");
2534 }
2535 } else if (Mnemonic == "at") {
2536 if (!Op.compare_lower("s1e1r")) {
2537 // SYS #0, C7, C8, #0
2538 SYS_ALIAS(0, 7, 8, 0);
2539 } else if (!Op.compare_lower("s1e2r")) {
2540 // SYS #4, C7, C8, #0
2541 SYS_ALIAS(4, 7, 8, 0);
2542 } else if (!Op.compare_lower("s1e3r")) {
2543 // SYS #6, C7, C8, #0
2544 SYS_ALIAS(6, 7, 8, 0);
2545 } else if (!Op.compare_lower("s1e1w")) {
2546 // SYS #0, C7, C8, #1
2547 SYS_ALIAS(0, 7, 8, 1);
2548 } else if (!Op.compare_lower("s1e2w")) {
2549 // SYS #4, C7, C8, #1
2550 SYS_ALIAS(4, 7, 8, 1);
2551 } else if (!Op.compare_lower("s1e3w")) {
2552 // SYS #6, C7, C8, #1
2553 SYS_ALIAS(6, 7, 8, 1);
2554 } else if (!Op.compare_lower("s1e0r")) {
2555 // SYS #0, C7, C8, #3
2556 SYS_ALIAS(0, 7, 8, 2);
2557 } else if (!Op.compare_lower("s1e0w")) {
2558 // SYS #0, C7, C8, #3
2559 SYS_ALIAS(0, 7, 8, 3);
2560 } else if (!Op.compare_lower("s12e1r")) {
2561 // SYS #4, C7, C8, #4
2562 SYS_ALIAS(4, 7, 8, 4);
2563 } else if (!Op.compare_lower("s12e1w")) {
2564 // SYS #4, C7, C8, #5
2565 SYS_ALIAS(4, 7, 8, 5);
2566 } else if (!Op.compare_lower("s12e0r")) {
2567 // SYS #4, C7, C8, #6
2568 SYS_ALIAS(4, 7, 8, 6);
2569 } else if (!Op.compare_lower("s12e0w")) {
2570 // SYS #4, C7, C8, #7
2571 SYS_ALIAS(4, 7, 8, 7);
Oliver Stannard64c167d2015-11-26 15:34:44 +00002572 } else if (!Op.compare_lower("s1e1rp")) {
2573 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2574 // SYS #0, C7, C9, #0
2575 SYS_ALIAS(0, 7, 9, 0);
2576 } else {
2577 return TokError("AT S1E1RP requires ARMv8.2a");
2578 }
2579 } else if (!Op.compare_lower("s1e1wp")) {
2580 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2581 // SYS #0, C7, C9, #1
2582 SYS_ALIAS(0, 7, 9, 1);
2583 } else {
2584 return TokError("AT S1E1WP requires ARMv8.2a");
2585 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002586 } else {
2587 return TokError("invalid operand for AT instruction");
2588 }
2589 } else if (Mnemonic == "tlbi") {
2590 if (!Op.compare_lower("vmalle1is")) {
2591 // SYS #0, C8, C3, #0
2592 SYS_ALIAS(0, 8, 3, 0);
2593 } else if (!Op.compare_lower("alle2is")) {
2594 // SYS #4, C8, C3, #0
2595 SYS_ALIAS(4, 8, 3, 0);
2596 } else if (!Op.compare_lower("alle3is")) {
2597 // SYS #6, C8, C3, #0
2598 SYS_ALIAS(6, 8, 3, 0);
2599 } else if (!Op.compare_lower("vae1is")) {
2600 // SYS #0, C8, C3, #1
2601 SYS_ALIAS(0, 8, 3, 1);
2602 } else if (!Op.compare_lower("vae2is")) {
2603 // SYS #4, C8, C3, #1
2604 SYS_ALIAS(4, 8, 3, 1);
2605 } else if (!Op.compare_lower("vae3is")) {
2606 // SYS #6, C8, C3, #1
2607 SYS_ALIAS(6, 8, 3, 1);
2608 } else if (!Op.compare_lower("aside1is")) {
2609 // SYS #0, C8, C3, #2
2610 SYS_ALIAS(0, 8, 3, 2);
2611 } else if (!Op.compare_lower("vaae1is")) {
2612 // SYS #0, C8, C3, #3
2613 SYS_ALIAS(0, 8, 3, 3);
2614 } else if (!Op.compare_lower("alle1is")) {
2615 // SYS #4, C8, C3, #4
2616 SYS_ALIAS(4, 8, 3, 4);
2617 } else if (!Op.compare_lower("vale1is")) {
2618 // SYS #0, C8, C3, #5
2619 SYS_ALIAS(0, 8, 3, 5);
2620 } else if (!Op.compare_lower("vaale1is")) {
2621 // SYS #0, C8, C3, #7
2622 SYS_ALIAS(0, 8, 3, 7);
2623 } else if (!Op.compare_lower("vmalle1")) {
2624 // SYS #0, C8, C7, #0
2625 SYS_ALIAS(0, 8, 7, 0);
2626 } else if (!Op.compare_lower("alle2")) {
2627 // SYS #4, C8, C7, #0
2628 SYS_ALIAS(4, 8, 7, 0);
2629 } else if (!Op.compare_lower("vale2is")) {
2630 // SYS #4, C8, C3, #5
2631 SYS_ALIAS(4, 8, 3, 5);
2632 } else if (!Op.compare_lower("vale3is")) {
2633 // SYS #6, C8, C3, #5
2634 SYS_ALIAS(6, 8, 3, 5);
2635 } else if (!Op.compare_lower("alle3")) {
2636 // SYS #6, C8, C7, #0
2637 SYS_ALIAS(6, 8, 7, 0);
2638 } else if (!Op.compare_lower("vae1")) {
2639 // SYS #0, C8, C7, #1
2640 SYS_ALIAS(0, 8, 7, 1);
2641 } else if (!Op.compare_lower("vae2")) {
2642 // SYS #4, C8, C7, #1
2643 SYS_ALIAS(4, 8, 7, 1);
2644 } else if (!Op.compare_lower("vae3")) {
2645 // SYS #6, C8, C7, #1
2646 SYS_ALIAS(6, 8, 7, 1);
2647 } else if (!Op.compare_lower("aside1")) {
2648 // SYS #0, C8, C7, #2
2649 SYS_ALIAS(0, 8, 7, 2);
2650 } else if (!Op.compare_lower("vaae1")) {
2651 // SYS #0, C8, C7, #3
2652 SYS_ALIAS(0, 8, 7, 3);
2653 } else if (!Op.compare_lower("alle1")) {
2654 // SYS #4, C8, C7, #4
2655 SYS_ALIAS(4, 8, 7, 4);
2656 } else if (!Op.compare_lower("vale1")) {
2657 // SYS #0, C8, C7, #5
2658 SYS_ALIAS(0, 8, 7, 5);
2659 } else if (!Op.compare_lower("vale2")) {
2660 // SYS #4, C8, C7, #5
2661 SYS_ALIAS(4, 8, 7, 5);
2662 } else if (!Op.compare_lower("vale3")) {
2663 // SYS #6, C8, C7, #5
2664 SYS_ALIAS(6, 8, 7, 5);
2665 } else if (!Op.compare_lower("vaale1")) {
2666 // SYS #0, C8, C7, #7
2667 SYS_ALIAS(0, 8, 7, 7);
2668 } else if (!Op.compare_lower("ipas2e1")) {
2669 // SYS #4, C8, C4, #1
2670 SYS_ALIAS(4, 8, 4, 1);
2671 } else if (!Op.compare_lower("ipas2le1")) {
2672 // SYS #4, C8, C4, #5
2673 SYS_ALIAS(4, 8, 4, 5);
2674 } else if (!Op.compare_lower("ipas2e1is")) {
2675 // SYS #4, C8, C4, #1
2676 SYS_ALIAS(4, 8, 0, 1);
2677 } else if (!Op.compare_lower("ipas2le1is")) {
2678 // SYS #4, C8, C4, #5
2679 SYS_ALIAS(4, 8, 0, 5);
2680 } else if (!Op.compare_lower("vmalls12e1")) {
2681 // SYS #4, C8, C7, #6
2682 SYS_ALIAS(4, 8, 7, 6);
2683 } else if (!Op.compare_lower("vmalls12e1is")) {
2684 // SYS #4, C8, C3, #6
2685 SYS_ALIAS(4, 8, 3, 6);
2686 } else {
2687 return TokError("invalid operand for TLBI instruction");
2688 }
2689 }
2690
2691#undef SYS_ALIAS
2692
2693 Parser.Lex(); // Eat operand.
2694
2695 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2696 bool HasRegister = false;
2697
2698 // Check for the optional register operand.
2699 if (getLexer().is(AsmToken::Comma)) {
2700 Parser.Lex(); // Eat comma.
2701
2702 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2703 return TokError("expected register operand");
2704
2705 HasRegister = true;
2706 }
2707
2708 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002709 return TokError("unexpected token in argument list");
2710 }
2711
2712 if (ExpectRegister && !HasRegister) {
2713 return TokError("specified " + Mnemonic + " op requires a register");
2714 }
2715 else if (!ExpectRegister && HasRegister) {
2716 return TokError("specified " + Mnemonic + " op does not use a register");
2717 }
2718
2719 Parser.Lex(); // Consume the EndOfStatement
2720 return false;
2721}
2722
2723AArch64AsmParser::OperandMatchResultTy
2724AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002725 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002726 const AsmToken &Tok = Parser.getTok();
2727
2728 // Can be either a #imm style literal or an option name
2729 bool Hash = Tok.is(AsmToken::Hash);
2730 if (Hash || Tok.is(AsmToken::Integer)) {
2731 // Immediate operand.
2732 if (Hash)
2733 Parser.Lex(); // Eat the '#'
2734 const MCExpr *ImmVal;
2735 SMLoc ExprLoc = getLoc();
2736 if (getParser().parseExpression(ImmVal))
2737 return MatchOperand_ParseFail;
2738 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2739 if (!MCE) {
2740 Error(ExprLoc, "immediate value expected for barrier operand");
2741 return MatchOperand_ParseFail;
2742 }
2743 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2744 Error(ExprLoc, "barrier operand out of range");
2745 return MatchOperand_ParseFail;
2746 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002747 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2748 Operands.push_back(AArch64Operand::CreateBarrier(
2749 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002750 return MatchOperand_Success;
2751 }
2752
2753 if (Tok.isNot(AsmToken::Identifier)) {
2754 TokError("invalid operand for instruction");
2755 return MatchOperand_ParseFail;
2756 }
2757
Tim Northovere6ae6762016-07-05 21:23:04 +00002758 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2759 if (!DB) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002760 TokError("invalid barrier option name");
2761 return MatchOperand_ParseFail;
2762 }
2763
2764 // The only valid named option for ISB is 'sy'
Tim Northovere6ae6762016-07-05 21:23:04 +00002765 if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002766 TokError("'sy' or #imm operand expected");
2767 return MatchOperand_ParseFail;
2768 }
2769
Tim Northovere6ae6762016-07-05 21:23:04 +00002770 Operands.push_back(AArch64Operand::CreateBarrier(
2771 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002772 Parser.Lex(); // Consume the option
2773
2774 return MatchOperand_Success;
2775}
2776
2777AArch64AsmParser::OperandMatchResultTy
2778AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002779 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002780 const AsmToken &Tok = Parser.getTok();
2781
2782 if (Tok.isNot(AsmToken::Identifier))
2783 return MatchOperand_NoMatch;
2784
Tim Northovere6ae6762016-07-05 21:23:04 +00002785 int MRSReg, MSRReg;
2786 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2787 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2788 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2789 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2790 } else
2791 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002792
Tim Northovere6ae6762016-07-05 21:23:04 +00002793 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2794 unsigned PStateImm = -1;
2795 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2796 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002797
Tim Northovere6ae6762016-07-05 21:23:04 +00002798 Operands.push_back(
2799 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2800 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002801 Parser.Lex(); // Eat identifier
2802
2803 return MatchOperand_Success;
2804}
2805
2806/// tryParseVectorRegister - Parse a vector register operand.
2807bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002808 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002809 if (Parser.getTok().isNot(AsmToken::Identifier))
2810 return true;
2811
2812 SMLoc S = getLoc();
2813 // Check for a vector register specifier first.
2814 StringRef Kind;
2815 int64_t Reg = tryMatchVectorRegister(Kind, false);
2816 if (Reg == -1)
2817 return true;
2818 Operands.push_back(
2819 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2820 // If there was an explicit qualifier, that goes on as a literal text
2821 // operand.
2822 if (!Kind.empty())
2823 Operands.push_back(
2824 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2825
2826 // If there is an index specifier following the register, parse that too.
2827 if (Parser.getTok().is(AsmToken::LBrac)) {
2828 SMLoc SIdx = getLoc();
2829 Parser.Lex(); // Eat left bracket token.
2830
2831 const MCExpr *ImmVal;
2832 if (getParser().parseExpression(ImmVal))
2833 return false;
2834 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2835 if (!MCE) {
2836 TokError("immediate value expected for vector index");
2837 return false;
2838 }
2839
2840 SMLoc E = getLoc();
2841 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2842 Error(E, "']' expected");
2843 return false;
2844 }
2845
2846 Parser.Lex(); // Eat right bracket token.
2847
2848 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2849 E, getContext()));
2850 }
2851
2852 return false;
2853}
2854
2855/// parseRegister - Parse a non-vector register operand.
2856bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002857 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002858 SMLoc S = getLoc();
2859 // Try for a vector register.
2860 if (!tryParseVectorRegister(Operands))
2861 return false;
2862
2863 // Try for a scalar register.
2864 int64_t Reg = tryParseRegister();
2865 if (Reg == -1)
2866 return true;
2867 Operands.push_back(
2868 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2869
2870 // A small number of instructions (FMOVXDhighr, for example) have "[1]"
2871 // as a string token in the instruction itself.
2872 if (getLexer().getKind() == AsmToken::LBrac) {
2873 SMLoc LBracS = getLoc();
2874 Parser.Lex();
2875 const AsmToken &Tok = Parser.getTok();
2876 if (Tok.is(AsmToken::Integer)) {
2877 SMLoc IntS = getLoc();
2878 int64_t Val = Tok.getIntVal();
2879 if (Val == 1) {
2880 Parser.Lex();
2881 if (getLexer().getKind() == AsmToken::RBrac) {
2882 SMLoc RBracS = getLoc();
2883 Parser.Lex();
2884 Operands.push_back(
2885 AArch64Operand::CreateToken("[", false, LBracS, getContext()));
2886 Operands.push_back(
2887 AArch64Operand::CreateToken("1", false, IntS, getContext()));
2888 Operands.push_back(
2889 AArch64Operand::CreateToken("]", false, RBracS, getContext()));
2890 return false;
2891 }
2892 }
2893 }
2894 }
2895
2896 return false;
2897}
2898
2899bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002900 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002901 bool HasELFModifier = false;
2902 AArch64MCExpr::VariantKind RefKind;
2903
2904 if (Parser.getTok().is(AsmToken::Colon)) {
2905 Parser.Lex(); // Eat ':"
2906 HasELFModifier = true;
2907
2908 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2909 Error(Parser.getTok().getLoc(),
2910 "expect relocation specifier in operand after ':'");
2911 return true;
2912 }
2913
2914 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2915 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2916 .Case("lo12", AArch64MCExpr::VK_LO12)
2917 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2918 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2919 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2920 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2921 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2922 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2923 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2924 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2925 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2926 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2927 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2928 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2929 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2930 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2931 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2932 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2933 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2934 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2935 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2936 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2937 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2938 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2939 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2940 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2941 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2942 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2943 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2944 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2945 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2946 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2947 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2948 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2949 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2950 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2951 .Default(AArch64MCExpr::VK_INVALID);
2952
2953 if (RefKind == AArch64MCExpr::VK_INVALID) {
2954 Error(Parser.getTok().getLoc(),
2955 "expect relocation specifier in operand after ':'");
2956 return true;
2957 }
2958
2959 Parser.Lex(); // Eat identifier
2960
2961 if (Parser.getTok().isNot(AsmToken::Colon)) {
2962 Error(Parser.getTok().getLoc(), "expect ':' after relocation specifier");
2963 return true;
2964 }
2965 Parser.Lex(); // Eat ':'
2966 }
2967
2968 if (getParser().parseExpression(ImmVal))
2969 return true;
2970
2971 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002972 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002973
2974 return false;
2975}
2976
2977/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2978bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002979 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002980 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2981 SMLoc S = getLoc();
2982 Parser.Lex(); // Eat left bracket token.
2983 StringRef Kind;
2984 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2985 if (FirstReg == -1)
2986 return true;
2987 int64_t PrevReg = FirstReg;
2988 unsigned Count = 1;
2989
2990 if (Parser.getTok().is(AsmToken::Minus)) {
2991 Parser.Lex(); // Eat the minus.
2992
2993 SMLoc Loc = getLoc();
2994 StringRef NextKind;
2995 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2996 if (Reg == -1)
2997 return true;
2998 // Any Kind suffices must match on all regs in the list.
2999 if (Kind != NextKind)
3000 return Error(Loc, "mismatched register size suffix");
3001
3002 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3003
3004 if (Space == 0 || Space > 3) {
3005 return Error(Loc, "invalid number of vectors");
3006 }
3007
3008 Count += Space;
3009 }
3010 else {
3011 while (Parser.getTok().is(AsmToken::Comma)) {
3012 Parser.Lex(); // Eat the comma token.
3013
3014 SMLoc Loc = getLoc();
3015 StringRef NextKind;
3016 int64_t Reg = tryMatchVectorRegister(NextKind, true);
3017 if (Reg == -1)
3018 return true;
3019 // Any Kind suffices must match on all regs in the list.
3020 if (Kind != NextKind)
3021 return Error(Loc, "mismatched register size suffix");
3022
3023 // Registers must be incremental (with wraparound at 31)
3024 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
3025 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
3026 return Error(Loc, "registers must be sequential");
3027
3028 PrevReg = Reg;
3029 ++Count;
3030 }
3031 }
3032
3033 if (Parser.getTok().isNot(AsmToken::RCurly))
3034 return Error(getLoc(), "'}' expected");
3035 Parser.Lex(); // Eat the '}' token.
3036
3037 if (Count > 4)
3038 return Error(S, "invalid number of vectors");
3039
3040 unsigned NumElements = 0;
3041 char ElementKind = 0;
3042 if (!Kind.empty())
3043 parseValidVectorKind(Kind, NumElements, ElementKind);
3044
3045 Operands.push_back(AArch64Operand::CreateVectorList(
3046 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
3047
3048 // If there is an index specifier following the list, parse that too.
3049 if (Parser.getTok().is(AsmToken::LBrac)) {
3050 SMLoc SIdx = getLoc();
3051 Parser.Lex(); // Eat left bracket token.
3052
3053 const MCExpr *ImmVal;
3054 if (getParser().parseExpression(ImmVal))
3055 return false;
3056 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3057 if (!MCE) {
3058 TokError("immediate value expected for vector index");
3059 return false;
3060 }
3061
3062 SMLoc E = getLoc();
3063 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3064 Error(E, "']' expected");
3065 return false;
3066 }
3067
3068 Parser.Lex(); // Eat right bracket token.
3069
3070 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3071 E, getContext()));
3072 }
3073 return false;
3074}
3075
3076AArch64AsmParser::OperandMatchResultTy
3077AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003078 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003079 const AsmToken &Tok = Parser.getTok();
3080 if (!Tok.is(AsmToken::Identifier))
3081 return MatchOperand_NoMatch;
3082
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003083 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00003084
3085 MCContext &Ctx = getContext();
3086 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3087 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3088 return MatchOperand_NoMatch;
3089
3090 SMLoc S = getLoc();
3091 Parser.Lex(); // Eat register
3092
3093 if (Parser.getTok().isNot(AsmToken::Comma)) {
3094 Operands.push_back(
3095 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3096 return MatchOperand_Success;
3097 }
3098 Parser.Lex(); // Eat comma.
3099
3100 if (Parser.getTok().is(AsmToken::Hash))
3101 Parser.Lex(); // Eat hash
3102
3103 if (Parser.getTok().isNot(AsmToken::Integer)) {
3104 Error(getLoc(), "index must be absent or #0");
3105 return MatchOperand_ParseFail;
3106 }
3107
3108 const MCExpr *ImmVal;
3109 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3110 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3111 Error(getLoc(), "index must be absent or #0");
3112 return MatchOperand_ParseFail;
3113 }
3114
3115 Operands.push_back(
3116 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3117 return MatchOperand_Success;
3118}
3119
3120/// parseOperand - Parse a arm instruction operand. For now this parses the
3121/// operand regardless of the mnemonic.
3122bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3123 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003124 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003125 // Check if the current operand has a custom associated parser, if so, try to
3126 // custom parse the operand, or fallback to the general approach.
3127 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3128 if (ResTy == MatchOperand_Success)
3129 return false;
3130 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3131 // there was a match, but an error occurred, in which case, just return that
3132 // the operand parsing failed.
3133 if (ResTy == MatchOperand_ParseFail)
3134 return true;
3135
3136 // Nothing custom, so do general case parsing.
3137 SMLoc S, E;
3138 switch (getLexer().getKind()) {
3139 default: {
3140 SMLoc S = getLoc();
3141 const MCExpr *Expr;
3142 if (parseSymbolicImmVal(Expr))
3143 return Error(S, "invalid operand");
3144
3145 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3146 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3147 return false;
3148 }
3149 case AsmToken::LBrac: {
3150 SMLoc Loc = Parser.getTok().getLoc();
3151 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3152 getContext()));
3153 Parser.Lex(); // Eat '['
3154
3155 // There's no comma after a '[', so we can parse the next operand
3156 // immediately.
3157 return parseOperand(Operands, false, false);
3158 }
3159 case AsmToken::LCurly:
3160 return parseVectorList(Operands);
3161 case AsmToken::Identifier: {
3162 // If we're expecting a Condition Code operand, then just parse that.
3163 if (isCondCode)
3164 return parseCondCode(Operands, invertCondCode);
3165
3166 // If it's a register name, parse it.
3167 if (!parseRegister(Operands))
3168 return false;
3169
3170 // This could be an optional "shift" or "extend" operand.
3171 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3172 // We can only continue if no tokens were eaten.
3173 if (GotShift != MatchOperand_NoMatch)
3174 return GotShift;
3175
3176 // This was not a register so parse other operands that start with an
3177 // identifier (like labels) as expressions and create them as immediates.
3178 const MCExpr *IdVal;
3179 S = getLoc();
3180 if (getParser().parseExpression(IdVal))
3181 return true;
3182
3183 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3184 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3185 return false;
3186 }
3187 case AsmToken::Integer:
3188 case AsmToken::Real:
3189 case AsmToken::Hash: {
3190 // #42 -> immediate.
3191 S = getLoc();
3192 if (getLexer().is(AsmToken::Hash))
3193 Parser.Lex();
3194
3195 // Parse a negative sign
3196 bool isNegative = false;
3197 if (Parser.getTok().is(AsmToken::Minus)) {
3198 isNegative = true;
3199 // We need to consume this token only when we have a Real, otherwise
3200 // we let parseSymbolicImmVal take care of it
3201 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3202 Parser.Lex();
3203 }
3204
3205 // The only Real that should come through here is a literal #0.0 for
3206 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3207 // so convert the value.
3208 const AsmToken &Tok = Parser.getTok();
3209 if (Tok.is(AsmToken::Real)) {
3210 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3211 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3212 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3213 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3214 Mnemonic != "fcmlt")
3215 return TokError("unexpected floating point literal");
3216 else if (IntVal != 0 || isNegative)
3217 return TokError("expected floating-point constant #0.0");
3218 Parser.Lex(); // Eat the token.
3219
3220 Operands.push_back(
3221 AArch64Operand::CreateToken("#0", false, S, getContext()));
3222 Operands.push_back(
3223 AArch64Operand::CreateToken(".0", false, S, getContext()));
3224 return false;
3225 }
3226
3227 const MCExpr *ImmVal;
3228 if (parseSymbolicImmVal(ImmVal))
3229 return true;
3230
3231 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3232 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3233 return false;
3234 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003235 case AsmToken::Equal: {
3236 SMLoc Loc = Parser.getTok().getLoc();
3237 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
3238 return Error(Loc, "unexpected token in operand");
3239 Parser.Lex(); // Eat '='
3240 const MCExpr *SubExprVal;
3241 if (getParser().parseExpression(SubExprVal))
3242 return true;
3243
David Peixottoae5ba762014-07-18 16:05:14 +00003244 if (Operands.size() < 2 ||
3245 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003246 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003247
3248 bool IsXReg =
3249 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3250 Operands[1]->getReg());
3251
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003252 MCContext& Ctx = getContext();
3253 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3254 // 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 +00003255 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003256 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3257 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3258 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3259 ShiftAmt += 16;
3260 Imm >>= 16;
3261 }
3262 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3263 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3264 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003265 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003266 if (ShiftAmt)
3267 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3268 ShiftAmt, true, S, E, Ctx));
3269 return false;
3270 }
David Peixottoae5ba762014-07-18 16:05:14 +00003271 APInt Simm = APInt(64, Imm << ShiftAmt);
3272 // check if the immediate is an unsigned or signed 32-bit int for W regs
3273 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3274 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003275 }
3276 // 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 +00003277 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003278 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003279 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3280 return false;
3281 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003282 }
3283}
3284
3285/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3286/// operands.
3287bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3288 StringRef Name, SMLoc NameLoc,
3289 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003290 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003291 Name = StringSwitch<StringRef>(Name.lower())
3292 .Case("beq", "b.eq")
3293 .Case("bne", "b.ne")
3294 .Case("bhs", "b.hs")
3295 .Case("bcs", "b.cs")
3296 .Case("blo", "b.lo")
3297 .Case("bcc", "b.cc")
3298 .Case("bmi", "b.mi")
3299 .Case("bpl", "b.pl")
3300 .Case("bvs", "b.vs")
3301 .Case("bvc", "b.vc")
3302 .Case("bhi", "b.hi")
3303 .Case("bls", "b.ls")
3304 .Case("bge", "b.ge")
3305 .Case("blt", "b.lt")
3306 .Case("bgt", "b.gt")
3307 .Case("ble", "b.le")
3308 .Case("bal", "b.al")
3309 .Case("bnv", "b.nv")
3310 .Default(Name);
3311
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003312 // First check for the AArch64-specific .req directive.
3313 if (Parser.getTok().is(AsmToken::Identifier) &&
3314 Parser.getTok().getIdentifier() == ".req") {
3315 parseDirectiveReq(Name, NameLoc);
3316 // We always return 'error' for this, as we're done with this
3317 // statement and don't need to match the 'instruction."
3318 return true;
3319 }
3320
Tim Northover3b0846e2014-05-24 12:50:23 +00003321 // Create the leading tokens for the mnemonic, split by '.' characters.
3322 size_t Start = 0, Next = Name.find('.');
3323 StringRef Head = Name.slice(Start, Next);
3324
3325 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
3326 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi") {
3327 bool IsError = parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003328 return IsError;
3329 }
3330
3331 Operands.push_back(
3332 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3333 Mnemonic = Head;
3334
3335 // Handle condition codes for a branch mnemonic
3336 if (Head == "b" && Next != StringRef::npos) {
3337 Start = Next;
3338 Next = Name.find('.', Start + 1);
3339 Head = Name.slice(Start + 1, Next);
3340
3341 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3342 (Head.data() - Name.data()));
3343 AArch64CC::CondCode CC = parseCondCodeString(Head);
3344 if (CC == AArch64CC::Invalid)
3345 return Error(SuffixLoc, "invalid condition code");
3346 Operands.push_back(
3347 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3348 Operands.push_back(
3349 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3350 }
3351
3352 // Add the remaining tokens in the mnemonic.
3353 while (Next != StringRef::npos) {
3354 Start = Next;
3355 Next = Name.find('.', Start + 1);
3356 Head = Name.slice(Start, Next);
3357 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3358 (Head.data() - Name.data()) + 1);
3359 Operands.push_back(
3360 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3361 }
3362
3363 // Conditional compare instructions have a Condition Code operand, which needs
3364 // to be parsed and an immediate operand created.
3365 bool condCodeFourthOperand =
3366 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3367 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3368 Head == "csinc" || Head == "csinv" || Head == "csneg");
3369
3370 // These instructions are aliases to some of the conditional select
3371 // instructions. However, the condition code is inverted in the aliased
3372 // instruction.
3373 //
3374 // FIXME: Is this the correct way to handle these? Or should the parser
3375 // generate the aliased instructions directly?
3376 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3377 bool condCodeThirdOperand =
3378 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3379
3380 // Read the remaining operands.
3381 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3382 // Read the first operand.
3383 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003384 return true;
3385 }
3386
3387 unsigned N = 2;
3388 while (getLexer().is(AsmToken::Comma)) {
3389 Parser.Lex(); // Eat the comma.
3390
3391 // Parse and remember the operand.
3392 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3393 (N == 3 && condCodeThirdOperand) ||
3394 (N == 2 && condCodeSecondOperand),
3395 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003396 return true;
3397 }
3398
3399 // After successfully parsing some operands there are two special cases to
3400 // consider (i.e. notional operands not separated by commas). Both are due
3401 // to memory specifiers:
3402 // + An RBrac will end an address for load/store/prefetch
3403 // + An '!' will indicate a pre-indexed operation.
3404 //
3405 // It's someone else's responsibility to make sure these tokens are sane
3406 // in the given context!
3407 if (Parser.getTok().is(AsmToken::RBrac)) {
3408 SMLoc Loc = Parser.getTok().getLoc();
3409 Operands.push_back(AArch64Operand::CreateToken("]", false, Loc,
3410 getContext()));
3411 Parser.Lex();
3412 }
3413
3414 if (Parser.getTok().is(AsmToken::Exclaim)) {
3415 SMLoc Loc = Parser.getTok().getLoc();
3416 Operands.push_back(AArch64Operand::CreateToken("!", false, Loc,
3417 getContext()));
3418 Parser.Lex();
3419 }
3420
3421 ++N;
3422 }
3423 }
3424
3425 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3426 SMLoc Loc = Parser.getTok().getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003427 return Error(Loc, "unexpected token in argument list");
3428 }
3429
3430 Parser.Lex(); // Consume the EndOfStatement
3431 return false;
3432}
3433
3434// FIXME: This entire function is a giant hack to provide us with decent
3435// operand range validation/diagnostics until TableGen/MC can be extended
3436// to support autogeneration of this kind of validation.
3437bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3438 SmallVectorImpl<SMLoc> &Loc) {
3439 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3440 // Check for indexed addressing modes w/ the base register being the
3441 // same as a destination/source register or pair load where
3442 // the Rt == Rt2. All of those are undefined behaviour.
3443 switch (Inst.getOpcode()) {
3444 case AArch64::LDPSWpre:
3445 case AArch64::LDPWpost:
3446 case AArch64::LDPWpre:
3447 case AArch64::LDPXpost:
3448 case AArch64::LDPXpre: {
3449 unsigned Rt = Inst.getOperand(1).getReg();
3450 unsigned Rt2 = Inst.getOperand(2).getReg();
3451 unsigned Rn = Inst.getOperand(3).getReg();
3452 if (RI->isSubRegisterEq(Rn, Rt))
3453 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3454 "is also a destination");
3455 if (RI->isSubRegisterEq(Rn, Rt2))
3456 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3457 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003458 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003459 }
3460 case AArch64::LDPDi:
3461 case AArch64::LDPQi:
3462 case AArch64::LDPSi:
3463 case AArch64::LDPSWi:
3464 case AArch64::LDPWi:
3465 case AArch64::LDPXi: {
3466 unsigned Rt = Inst.getOperand(0).getReg();
3467 unsigned Rt2 = Inst.getOperand(1).getReg();
3468 if (Rt == Rt2)
3469 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3470 break;
3471 }
3472 case AArch64::LDPDpost:
3473 case AArch64::LDPDpre:
3474 case AArch64::LDPQpost:
3475 case AArch64::LDPQpre:
3476 case AArch64::LDPSpost:
3477 case AArch64::LDPSpre:
3478 case AArch64::LDPSWpost: {
3479 unsigned Rt = Inst.getOperand(1).getReg();
3480 unsigned Rt2 = Inst.getOperand(2).getReg();
3481 if (Rt == Rt2)
3482 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3483 break;
3484 }
3485 case AArch64::STPDpost:
3486 case AArch64::STPDpre:
3487 case AArch64::STPQpost:
3488 case AArch64::STPQpre:
3489 case AArch64::STPSpost:
3490 case AArch64::STPSpre:
3491 case AArch64::STPWpost:
3492 case AArch64::STPWpre:
3493 case AArch64::STPXpost:
3494 case AArch64::STPXpre: {
3495 unsigned Rt = Inst.getOperand(1).getReg();
3496 unsigned Rt2 = Inst.getOperand(2).getReg();
3497 unsigned Rn = Inst.getOperand(3).getReg();
3498 if (RI->isSubRegisterEq(Rn, Rt))
3499 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3500 "is also a source");
3501 if (RI->isSubRegisterEq(Rn, Rt2))
3502 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3503 "is also a source");
3504 break;
3505 }
3506 case AArch64::LDRBBpre:
3507 case AArch64::LDRBpre:
3508 case AArch64::LDRHHpre:
3509 case AArch64::LDRHpre:
3510 case AArch64::LDRSBWpre:
3511 case AArch64::LDRSBXpre:
3512 case AArch64::LDRSHWpre:
3513 case AArch64::LDRSHXpre:
3514 case AArch64::LDRSWpre:
3515 case AArch64::LDRWpre:
3516 case AArch64::LDRXpre:
3517 case AArch64::LDRBBpost:
3518 case AArch64::LDRBpost:
3519 case AArch64::LDRHHpost:
3520 case AArch64::LDRHpost:
3521 case AArch64::LDRSBWpost:
3522 case AArch64::LDRSBXpost:
3523 case AArch64::LDRSHWpost:
3524 case AArch64::LDRSHXpost:
3525 case AArch64::LDRSWpost:
3526 case AArch64::LDRWpost:
3527 case AArch64::LDRXpost: {
3528 unsigned Rt = Inst.getOperand(1).getReg();
3529 unsigned Rn = Inst.getOperand(2).getReg();
3530 if (RI->isSubRegisterEq(Rn, Rt))
3531 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3532 "is also a source");
3533 break;
3534 }
3535 case AArch64::STRBBpost:
3536 case AArch64::STRBpost:
3537 case AArch64::STRHHpost:
3538 case AArch64::STRHpost:
3539 case AArch64::STRWpost:
3540 case AArch64::STRXpost:
3541 case AArch64::STRBBpre:
3542 case AArch64::STRBpre:
3543 case AArch64::STRHHpre:
3544 case AArch64::STRHpre:
3545 case AArch64::STRWpre:
3546 case AArch64::STRXpre: {
3547 unsigned Rt = Inst.getOperand(1).getReg();
3548 unsigned Rn = Inst.getOperand(2).getReg();
3549 if (RI->isSubRegisterEq(Rn, Rt))
3550 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3551 "is also a source");
3552 break;
3553 }
3554 }
3555
3556 // Now check immediate ranges. Separate from the above as there is overlap
3557 // in the instructions being checked and this keeps the nested conditionals
3558 // to a minimum.
3559 switch (Inst.getOpcode()) {
3560 case AArch64::ADDSWri:
3561 case AArch64::ADDSXri:
3562 case AArch64::ADDWri:
3563 case AArch64::ADDXri:
3564 case AArch64::SUBSWri:
3565 case AArch64::SUBSXri:
3566 case AArch64::SUBWri:
3567 case AArch64::SUBXri: {
3568 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3569 // some slight duplication here.
3570 if (Inst.getOperand(2).isExpr()) {
3571 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3572 AArch64MCExpr::VariantKind ELFRefKind;
3573 MCSymbolRefExpr::VariantKind DarwinRefKind;
3574 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003575 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3576
3577 // Only allow these with ADDXri.
3578 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3579 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3580 Inst.getOpcode() == AArch64::ADDXri)
3581 return false;
3582
3583 // Only allow these with ADDXri/ADDWri
3584 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3585 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3586 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3587 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3588 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3589 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3590 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3591 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3592 (Inst.getOpcode() == AArch64::ADDXri ||
3593 Inst.getOpcode() == AArch64::ADDWri))
3594 return false;
3595
3596 // Don't allow symbol refs in the immediate field otherwise
3597 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3598 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3599 // 'cmp w0, 'borked')
3600 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003601 }
Diana Picusc93518d2016-10-11 09:17:47 +00003602 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003603 }
3604 return false;
3605 }
3606 default:
3607 return false;
3608 }
3609}
3610
3611bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3612 switch (ErrCode) {
3613 case Match_MissingFeature:
3614 return Error(Loc,
3615 "instruction requires a CPU feature not currently enabled");
3616 case Match_InvalidOperand:
3617 return Error(Loc, "invalid operand for instruction");
3618 case Match_InvalidSuffix:
3619 return Error(Loc, "invalid type suffix for instruction");
3620 case Match_InvalidCondCode:
3621 return Error(Loc, "expected AArch64 condition code");
3622 case Match_AddSubRegExtendSmall:
3623 return Error(Loc,
3624 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3625 case Match_AddSubRegExtendLarge:
3626 return Error(Loc,
3627 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3628 case Match_AddSubSecondSource:
3629 return Error(Loc,
3630 "expected compatible register, symbol or integer in range [0, 4095]");
3631 case Match_LogicalSecondSource:
3632 return Error(Loc, "expected compatible register or logical immediate");
3633 case Match_InvalidMovImm32Shift:
3634 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3635 case Match_InvalidMovImm64Shift:
3636 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3637 case Match_AddSubRegShift32:
3638 return Error(Loc,
3639 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3640 case Match_AddSubRegShift64:
3641 return Error(Loc,
3642 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3643 case Match_InvalidFPImm:
3644 return Error(Loc,
3645 "expected compatible register or floating-point constant");
3646 case Match_InvalidMemoryIndexedSImm9:
3647 return Error(Loc, "index must be an integer in range [-256, 255].");
3648 case Match_InvalidMemoryIndexed4SImm7:
3649 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3650 case Match_InvalidMemoryIndexed8SImm7:
3651 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3652 case Match_InvalidMemoryIndexed16SImm7:
3653 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3654 case Match_InvalidMemoryWExtend8:
3655 return Error(Loc,
3656 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3657 case Match_InvalidMemoryWExtend16:
3658 return Error(Loc,
3659 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3660 case Match_InvalidMemoryWExtend32:
3661 return Error(Loc,
3662 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3663 case Match_InvalidMemoryWExtend64:
3664 return Error(Loc,
3665 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3666 case Match_InvalidMemoryWExtend128:
3667 return Error(Loc,
3668 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3669 case Match_InvalidMemoryXExtend8:
3670 return Error(Loc,
3671 "expected 'lsl' or 'sxtx' with optional shift of #0");
3672 case Match_InvalidMemoryXExtend16:
3673 return Error(Loc,
3674 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3675 case Match_InvalidMemoryXExtend32:
3676 return Error(Loc,
3677 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3678 case Match_InvalidMemoryXExtend64:
3679 return Error(Loc,
3680 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3681 case Match_InvalidMemoryXExtend128:
3682 return Error(Loc,
3683 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3684 case Match_InvalidMemoryIndexed1:
3685 return Error(Loc, "index must be an integer in range [0, 4095].");
3686 case Match_InvalidMemoryIndexed2:
3687 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3688 case Match_InvalidMemoryIndexed4:
3689 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3690 case Match_InvalidMemoryIndexed8:
3691 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3692 case Match_InvalidMemoryIndexed16:
3693 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003694 case Match_InvalidImm0_1:
3695 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003696 case Match_InvalidImm0_7:
3697 return Error(Loc, "immediate must be an integer in range [0, 7].");
3698 case Match_InvalidImm0_15:
3699 return Error(Loc, "immediate must be an integer in range [0, 15].");
3700 case Match_InvalidImm0_31:
3701 return Error(Loc, "immediate must be an integer in range [0, 31].");
3702 case Match_InvalidImm0_63:
3703 return Error(Loc, "immediate must be an integer in range [0, 63].");
3704 case Match_InvalidImm0_127:
3705 return Error(Loc, "immediate must be an integer in range [0, 127].");
3706 case Match_InvalidImm0_65535:
3707 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3708 case Match_InvalidImm1_8:
3709 return Error(Loc, "immediate must be an integer in range [1, 8].");
3710 case Match_InvalidImm1_16:
3711 return Error(Loc, "immediate must be an integer in range [1, 16].");
3712 case Match_InvalidImm1_32:
3713 return Error(Loc, "immediate must be an integer in range [1, 32].");
3714 case Match_InvalidImm1_64:
3715 return Error(Loc, "immediate must be an integer in range [1, 64].");
3716 case Match_InvalidIndex1:
3717 return Error(Loc, "expected lane specifier '[1]'");
3718 case Match_InvalidIndexB:
3719 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3720 case Match_InvalidIndexH:
3721 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3722 case Match_InvalidIndexS:
3723 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3724 case Match_InvalidIndexD:
3725 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3726 case Match_InvalidLabel:
3727 return Error(Loc, "expected label or encodable integer pc offset");
3728 case Match_MRS:
3729 return Error(Loc, "expected readable system register");
3730 case Match_MSR:
3731 return Error(Loc, "expected writable system register or pstate");
3732 case Match_MnemonicFail:
3733 return Error(Loc, "unrecognized instruction mnemonic");
3734 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003735 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003736 }
3737}
3738
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003739static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003740
3741bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3742 OperandVector &Operands,
3743 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003744 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003745 bool MatchingInlineAsm) {
3746 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003747 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3748 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003749
David Blaikie960ea3f2014-06-08 16:18:35 +00003750 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003751 unsigned NumOperands = Operands.size();
3752
3753 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003754 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3755 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3756 if (Op2.isReg() && Op3.isImm()) {
3757 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003758 if (Op3CE) {
3759 uint64_t Op3Val = Op3CE->getValue();
3760 uint64_t NewOp3Val = 0;
3761 uint64_t NewOp4Val = 0;
3762 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003763 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003764 NewOp3Val = (32 - Op3Val) & 0x1f;
3765 NewOp4Val = 31 - Op3Val;
3766 } else {
3767 NewOp3Val = (64 - Op3Val) & 0x3f;
3768 NewOp4Val = 63 - Op3Val;
3769 }
3770
Jim Grosbach13760bd2015-05-30 01:25:56 +00003771 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3772 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003773
3774 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003775 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003776 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003777 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3778 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3779 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003780 }
3781 }
Tim Northover03b99f62015-04-30 18:28:58 +00003782 } else if (NumOperands == 4 && Tok == "bfc") {
3783 // FIXME: Horrible hack to handle BFC->BFM alias.
3784 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3785 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3786 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3787
3788 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3789 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3790 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3791
3792 if (LSBCE && WidthCE) {
3793 uint64_t LSB = LSBCE->getValue();
3794 uint64_t Width = WidthCE->getValue();
3795
3796 uint64_t RegWidth = 0;
3797 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3798 Op1.getReg()))
3799 RegWidth = 64;
3800 else
3801 RegWidth = 32;
3802
3803 if (LSB >= RegWidth)
3804 return Error(LSBOp.getStartLoc(),
3805 "expected integer in range [0, 31]");
3806 if (Width < 1 || Width > RegWidth)
3807 return Error(WidthOp.getStartLoc(),
3808 "expected integer in range [1, 32]");
3809
3810 uint64_t ImmR = 0;
3811 if (RegWidth == 32)
3812 ImmR = (32 - LSB) & 0x1f;
3813 else
3814 ImmR = (64 - LSB) & 0x3f;
3815
3816 uint64_t ImmS = Width - 1;
3817
3818 if (ImmR != 0 && ImmS >= ImmR)
3819 return Error(WidthOp.getStartLoc(),
3820 "requested insert overflows register");
3821
Jim Grosbach13760bd2015-05-30 01:25:56 +00003822 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3823 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003824 Operands[0] = AArch64Operand::CreateToken(
3825 "bfm", false, Op.getStartLoc(), getContext());
3826 Operands[2] = AArch64Operand::CreateReg(
3827 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3828 SMLoc(), getContext());
3829 Operands[3] = AArch64Operand::CreateImm(
3830 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3831 Operands.emplace_back(
3832 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3833 WidthOp.getEndLoc(), getContext()));
3834 }
3835 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003836 } else if (NumOperands == 5) {
3837 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3838 // UBFIZ -> UBFM aliases.
3839 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003840 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3841 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3842 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003843
David Blaikie960ea3f2014-06-08 16:18:35 +00003844 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3845 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3846 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003847
3848 if (Op3CE && Op4CE) {
3849 uint64_t Op3Val = Op3CE->getValue();
3850 uint64_t Op4Val = Op4CE->getValue();
3851
3852 uint64_t RegWidth = 0;
3853 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003854 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003855 RegWidth = 64;
3856 else
3857 RegWidth = 32;
3858
3859 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003860 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 "expected integer in range [0, 31]");
3862 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003863 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003864 "expected integer in range [1, 32]");
3865
3866 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003867 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003868 NewOp3Val = (32 - Op3Val) & 0x1f;
3869 else
3870 NewOp3Val = (64 - Op3Val) & 0x3f;
3871
3872 uint64_t NewOp4Val = Op4Val - 1;
3873
3874 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003875 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003876 "requested insert overflows register");
3877
3878 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003879 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003880 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003881 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003882 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003883 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003884 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003885 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003886 if (Tok == "bfi")
3887 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003888 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003889 else if (Tok == "sbfiz")
3890 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003891 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003892 else if (Tok == "ubfiz")
3893 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003894 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003895 else
3896 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003897 }
3898 }
3899
3900 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3901 // UBFX -> UBFM aliases.
3902 } else if (NumOperands == 5 &&
3903 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003904 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3905 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3906 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003907
David Blaikie960ea3f2014-06-08 16:18:35 +00003908 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3909 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3910 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003911
3912 if (Op3CE && Op4CE) {
3913 uint64_t Op3Val = Op3CE->getValue();
3914 uint64_t Op4Val = Op4CE->getValue();
3915
3916 uint64_t RegWidth = 0;
3917 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003918 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003919 RegWidth = 64;
3920 else
3921 RegWidth = 32;
3922
3923 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003924 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003925 "expected integer in range [0, 31]");
3926 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003927 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003928 "expected integer in range [1, 32]");
3929
3930 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3931
3932 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003933 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003934 "requested extract overflows register");
3935
3936 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003937 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003938 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003939 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 if (Tok == "bfxil")
3941 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003942 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003943 else if (Tok == "sbfx")
3944 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003945 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003946 else if (Tok == "ubfx")
3947 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003948 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003949 else
3950 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003951 }
3952 }
3953 }
3954 }
3955 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3956 // InstAlias can't quite handle this since the reg classes aren't
3957 // subclasses.
3958 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3959 // The source register can be Wn here, but the matcher expects a
3960 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003961 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3962 if (Op.isReg()) {
3963 unsigned Reg = getXRegFromWReg(Op.getReg());
3964 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3965 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003966 }
3967 }
3968 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3969 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003970 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3971 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003972 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003973 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003974 // The source register can be Wn here, but the matcher expects a
3975 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003976 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3977 if (Op.isReg()) {
3978 unsigned Reg = getXRegFromWReg(Op.getReg());
3979 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3980 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003981 }
3982 }
3983 }
3984 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3985 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003986 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3987 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003988 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003989 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003990 // The source register can be Wn here, but the matcher expects a
3991 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003992 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3993 if (Op.isReg()) {
3994 unsigned Reg = getWRegFromXReg(Op.getReg());
3995 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3996 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003997 }
3998 }
3999 }
4000
4001 // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
4002 if (NumOperands == 3 && Tok == "fmov") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004003 AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
4004 AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
4005 if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004006 unsigned zreg =
Oliver Stannardb25914e2015-11-27 13:04:48 +00004007 !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004008 RegOp.getReg())
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 ? AArch64::WZR
4010 : AArch64::XZR;
David Blaikie960ea3f2014-06-08 16:18:35 +00004011 Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
4012 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004013 }
4014 }
4015
4016 MCInst Inst;
4017 // First try to match against the secondary set of tables containing the
4018 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4019 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004020 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004021
4022 // If that fails, try against the alternate table containing long-form NEON:
4023 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004024 if (MatchResult != Match_Success) {
4025 // But first, save the short-form match result: we can use it in case the
4026 // long-form match also fails.
4027 auto ShortFormNEONErrorInfo = ErrorInfo;
4028 auto ShortFormNEONMatchResult = MatchResult;
4029
Tim Northover3b0846e2014-05-24 12:50:23 +00004030 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004031 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004032
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004033 // Now, both matches failed, and the long-form match failed on the mnemonic
4034 // suffix token operand. The short-form match failure is probably more
4035 // relevant: use it instead.
4036 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004037 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004038 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4039 MatchResult = ShortFormNEONMatchResult;
4040 ErrorInfo = ShortFormNEONErrorInfo;
4041 }
4042 }
4043
4044
Tim Northover3b0846e2014-05-24 12:50:23 +00004045 switch (MatchResult) {
4046 case Match_Success: {
4047 // Perform range checking and other semantic validations
4048 SmallVector<SMLoc, 8> OperandLocs;
4049 NumOperands = Operands.size();
4050 for (unsigned i = 1; i < NumOperands; ++i)
4051 OperandLocs.push_back(Operands[i]->getStartLoc());
4052 if (validateInstruction(Inst, OperandLocs))
4053 return true;
4054
4055 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004056 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004057 return false;
4058 }
4059 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004060 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004061 // Special case the error message for the very common case where only
4062 // a single subtarget feature is missing (neon, e.g.).
4063 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004064 uint64_t Mask = 1;
4065 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4066 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004067 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004068 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004069 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004070 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004071 }
4072 return Error(IDLoc, Msg);
4073 }
4074 case Match_MnemonicFail:
4075 return showMatchError(IDLoc, MatchResult);
4076 case Match_InvalidOperand: {
4077 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004078
Tim Northover26bb14e2014-08-18 11:49:42 +00004079 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004080 if (ErrorInfo >= Operands.size())
4081 return Error(IDLoc, "too few operands for instruction");
4082
David Blaikie960ea3f2014-06-08 16:18:35 +00004083 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 if (ErrorLoc == SMLoc())
4085 ErrorLoc = IDLoc;
4086 }
4087 // If the match failed on a suffix token operand, tweak the diagnostic
4088 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004089 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4090 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004091 MatchResult = Match_InvalidSuffix;
4092
4093 return showMatchError(ErrorLoc, MatchResult);
4094 }
4095 case Match_InvalidMemoryIndexed1:
4096 case Match_InvalidMemoryIndexed2:
4097 case Match_InvalidMemoryIndexed4:
4098 case Match_InvalidMemoryIndexed8:
4099 case Match_InvalidMemoryIndexed16:
4100 case Match_InvalidCondCode:
4101 case Match_AddSubRegExtendSmall:
4102 case Match_AddSubRegExtendLarge:
4103 case Match_AddSubSecondSource:
4104 case Match_LogicalSecondSource:
4105 case Match_AddSubRegShift32:
4106 case Match_AddSubRegShift64:
4107 case Match_InvalidMovImm32Shift:
4108 case Match_InvalidMovImm64Shift:
4109 case Match_InvalidFPImm:
4110 case Match_InvalidMemoryWExtend8:
4111 case Match_InvalidMemoryWExtend16:
4112 case Match_InvalidMemoryWExtend32:
4113 case Match_InvalidMemoryWExtend64:
4114 case Match_InvalidMemoryWExtend128:
4115 case Match_InvalidMemoryXExtend8:
4116 case Match_InvalidMemoryXExtend16:
4117 case Match_InvalidMemoryXExtend32:
4118 case Match_InvalidMemoryXExtend64:
4119 case Match_InvalidMemoryXExtend128:
4120 case Match_InvalidMemoryIndexed4SImm7:
4121 case Match_InvalidMemoryIndexed8SImm7:
4122 case Match_InvalidMemoryIndexed16SImm7:
4123 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004124 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004125 case Match_InvalidImm0_7:
4126 case Match_InvalidImm0_15:
4127 case Match_InvalidImm0_31:
4128 case Match_InvalidImm0_63:
4129 case Match_InvalidImm0_127:
4130 case Match_InvalidImm0_65535:
4131 case Match_InvalidImm1_8:
4132 case Match_InvalidImm1_16:
4133 case Match_InvalidImm1_32:
4134 case Match_InvalidImm1_64:
4135 case Match_InvalidIndex1:
4136 case Match_InvalidIndexB:
4137 case Match_InvalidIndexH:
4138 case Match_InvalidIndexS:
4139 case Match_InvalidIndexD:
4140 case Match_InvalidLabel:
4141 case Match_MSR:
4142 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004143 if (ErrorInfo >= Operands.size())
4144 return Error(IDLoc, "too few operands for instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00004145 // Any time we get here, there's nothing fancy to do. Just get the
4146 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004147 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004148 if (ErrorLoc == SMLoc())
4149 ErrorLoc = IDLoc;
4150 return showMatchError(ErrorLoc, MatchResult);
4151 }
4152 }
4153
4154 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004155}
4156
4157/// ParseDirective parses the arm specific directives
4158bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004159 const MCObjectFileInfo::Environment Format =
4160 getContext().getObjectFileInfo()->getObjectFileType();
4161 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4162 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004163
Tim Northover3b0846e2014-05-24 12:50:23 +00004164 StringRef IDVal = DirectiveID.getIdentifier();
4165 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004166 if (IDVal == ".arch")
4167 return parseDirectiveArch(Loc);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004168 if (IDVal == ".cpu")
4169 return parseDirectiveCPU(Loc);
Tim Northover3b0846e2014-05-24 12:50:23 +00004170 if (IDVal == ".hword")
4171 return parseDirectiveWord(2, Loc);
4172 if (IDVal == ".word")
4173 return parseDirectiveWord(4, Loc);
4174 if (IDVal == ".xword")
4175 return parseDirectiveWord(8, Loc);
4176 if (IDVal == ".tlsdesccall")
4177 return parseDirectiveTLSDescCall(Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004178 if (IDVal == ".ltorg" || IDVal == ".pool")
4179 return parseDirectiveLtorg(Loc);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004180 if (IDVal == ".unreq")
Chad Rosieradc06312015-05-28 18:18:21 +00004181 return parseDirectiveUnreq(Loc);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004182
Chad Rosierdcd2a302014-10-22 20:35:57 +00004183 if (!IsMachO && !IsCOFF) {
4184 if (IDVal == ".inst")
4185 return parseDirectiveInst(Loc);
4186 }
Nirav Dave2364748a2016-09-16 18:30:20 +00004187 if (IDVal == MCLOHDirectiveName())
4188 return parseDirectiveLOH(IDVal, Loc);
Chad Rosierdcd2a302014-10-22 20:35:57 +00004189
Nirav Dave2364748a2016-09-16 18:30:20 +00004190 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004191}
4192
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004193static const struct {
4194 const char *Name;
4195 const FeatureBitset Features;
4196} ExtensionMap[] = {
4197 { "crc", {AArch64::FeatureCRC} },
4198 { "crypto", {AArch64::FeatureCrypto} },
4199 { "fp", {AArch64::FeatureFPARMv8} },
4200 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004201 { "ras", {AArch64::FeatureRAS} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004202
4203 // FIXME: Unsupported extensions
4204 { "lse", {} },
4205 { "pan", {} },
4206 { "lor", {} },
4207 { "rdma", {} },
4208 { "profile", {} },
4209};
4210
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004211/// parseDirectiveArch
4212/// ::= .arch token
4213bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4214 SMLoc ArchLoc = getLoc();
4215
4216 StringRef Arch, ExtensionString;
4217 std::tie(Arch, ExtensionString) =
4218 getParser().parseStringToEndOfStatement().trim().split('+');
4219
4220 unsigned ID = AArch64::parseArch(Arch);
Zijiao Mae56a53a2016-07-28 06:11:18 +00004221 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID)) {
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004222 Error(ArchLoc, "unknown arch name");
4223 return false;
4224 }
4225
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004226 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004227 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004228 AArch64::getArchFeatures(ID, AArch64Features);
4229 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4230 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004231
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004232 MCSubtargetInfo &STI = copySTI();
4233 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4234 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4235
4236 SmallVector<StringRef, 4> RequestedExtensions;
4237 if (!ExtensionString.empty())
4238 ExtensionString.split(RequestedExtensions, '+');
4239
4240 FeatureBitset Features = STI.getFeatureBits();
4241 for (auto Name : RequestedExtensions) {
4242 bool EnableFeature = true;
4243
4244 if (Name.startswith_lower("no")) {
4245 EnableFeature = false;
4246 Name = Name.substr(2);
4247 }
4248
4249 for (const auto &Extension : ExtensionMap) {
4250 if (Extension.Name != Name)
4251 continue;
4252
4253 if (Extension.Features.none())
4254 report_fatal_error("unsupported architectural extension: " + Name);
4255
4256 FeatureBitset ToggleFeatures = EnableFeature
4257 ? (~Features & Extension.Features)
4258 : ( Features & Extension.Features);
4259 uint64_t Features =
4260 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4261 setAvailableFeatures(Features);
4262 break;
4263 }
4264 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004265 return false;
4266}
4267
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004268/// parseDirectiveCPU
4269/// ::= .cpu id
4270bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
4271 SMLoc CPULoc = getLoc();
4272
4273 StringRef CPU, ExtensionString;
4274 std::tie(CPU, ExtensionString) =
4275 getParser().parseStringToEndOfStatement().trim().split('+');
4276
4277 SmallVector<StringRef, 4> RequestedExtensions;
4278 if (!ExtensionString.empty())
4279 ExtensionString.split(RequestedExtensions, '+');
4280
4281 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4282 // once that is tablegen'ed
4283 if (!getSTI().isCPUStringValid(CPU)) {
4284 Error(CPULoc, "unknown CPU name");
4285 return false;
4286 }
4287
4288 MCSubtargetInfo &STI = copySTI();
4289 STI.setDefaultFeatures(CPU, "");
4290
4291 FeatureBitset Features = STI.getFeatureBits();
4292 for (auto Name : RequestedExtensions) {
4293 bool EnableFeature = true;
4294
4295 if (Name.startswith_lower("no")) {
4296 EnableFeature = false;
4297 Name = Name.substr(2);
4298 }
4299
4300 for (const auto &Extension : ExtensionMap) {
4301 if (Extension.Name != Name)
4302 continue;
4303
4304 if (Extension.Features.none())
4305 report_fatal_error("unsupported architectural extension: " + Name);
4306
4307 FeatureBitset ToggleFeatures = EnableFeature
4308 ? (~Features & Extension.Features)
4309 : ( Features & Extension.Features);
4310 uint64_t Features =
4311 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4312 setAvailableFeatures(Features);
4313
4314 break;
4315 }
4316 }
4317 return false;
4318}
4319
Tim Northover3b0846e2014-05-24 12:50:23 +00004320/// parseDirectiveWord
4321/// ::= .word [ expression (, expression)* ]
4322bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004323 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00004324 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4325 for (;;) {
4326 const MCExpr *Value;
4327 if (getParser().parseExpression(Value))
4328 return true;
4329
Oliver Stannard09be0602015-11-16 16:22:47 +00004330 getParser().getStreamer().EmitValue(Value, Size, L);
Tim Northover3b0846e2014-05-24 12:50:23 +00004331
4332 if (getLexer().is(AsmToken::EndOfStatement))
4333 break;
4334
4335 // FIXME: Improve diagnostic.
4336 if (getLexer().isNot(AsmToken::Comma))
4337 return Error(L, "unexpected token in directive");
4338 Parser.Lex();
4339 }
4340 }
4341
4342 Parser.Lex();
4343 return false;
4344}
4345
Chad Rosierdcd2a302014-10-22 20:35:57 +00004346/// parseDirectiveInst
4347/// ::= .inst opcode [, ...]
4348bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004349 MCAsmParser &Parser = getParser();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004350 if (getLexer().is(AsmToken::EndOfStatement)) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004351 Error(Loc, "expected expression following directive");
4352 return false;
4353 }
4354
4355 for (;;) {
4356 const MCExpr *Expr;
4357
4358 if (getParser().parseExpression(Expr)) {
4359 Error(Loc, "expected expression");
4360 return false;
4361 }
4362
4363 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
4364 if (!Value) {
4365 Error(Loc, "expected constant expression");
4366 return false;
4367 }
4368
4369 getTargetStreamer().emitInst(Value->getValue());
4370
4371 if (getLexer().is(AsmToken::EndOfStatement))
4372 break;
4373
4374 if (getLexer().isNot(AsmToken::Comma)) {
4375 Error(Loc, "unexpected token in directive");
4376 return false;
4377 }
4378
4379 Parser.Lex(); // Eat comma.
4380 }
4381
4382 Parser.Lex();
4383 return false;
4384}
4385
Tim Northover3b0846e2014-05-24 12:50:23 +00004386// parseDirectiveTLSDescCall:
4387// ::= .tlsdesccall symbol
4388bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4389 StringRef Name;
4390 if (getParser().parseIdentifier(Name))
4391 return Error(L, "expected symbol after directive");
4392
Jim Grosbach6f482002015-05-18 18:43:14 +00004393 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004394 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4395 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004396
4397 MCInst Inst;
4398 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004399 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004400
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004401 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004402 return false;
4403}
4404
4405/// ::= .loh <lohName | lohId> label1, ..., labelN
4406/// The number of arguments depends on the loh identifier.
4407bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004408 MCLOHType Kind;
4409 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4410 if (getParser().getTok().isNot(AsmToken::Integer))
4411 return TokError("expected an identifier or a number in directive");
4412 // We successfully get a numeric value for the identifier.
4413 // Check if it is valid.
4414 int64_t Id = getParser().getTok().getIntVal();
Nirav Dave2364748a2016-09-16 18:30:20 +00004415 if (Id <= -1U && !isValidMCLOHType(Id)) {
4416 TokError("invalid numeric identifier in directive");
4417 return false;
4418 }
Alexey Samsonov700964e2014-08-29 22:34:28 +00004419 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004420 } else {
4421 StringRef Name = getTok().getIdentifier();
4422 // We successfully parse an identifier.
4423 // Check if it is a recognized one.
4424 int Id = MCLOHNameToId(Name);
4425
4426 if (Id == -1)
4427 return TokError("invalid identifier in directive");
4428 Kind = (MCLOHType)Id;
4429 }
4430 // Consume the identifier.
4431 Lex();
4432 // Get the number of arguments of this LOH.
4433 int NbArgs = MCLOHIdToNbArgs(Kind);
4434
4435 assert(NbArgs != -1 && "Invalid number of arguments");
4436
4437 SmallVector<MCSymbol *, 3> Args;
4438 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4439 StringRef Name;
4440 if (getParser().parseIdentifier(Name))
4441 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004442 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004443
4444 if (Idx + 1 == NbArgs)
4445 break;
4446 if (getLexer().isNot(AsmToken::Comma))
4447 return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
4448 Lex();
4449 }
4450 if (getLexer().isNot(AsmToken::EndOfStatement))
4451 return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
4452
4453 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4454 return false;
4455}
4456
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004457/// parseDirectiveLtorg
4458/// ::= .ltorg | .pool
4459bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
4460 getTargetStreamer().emitCurrentConstantPool();
4461 return false;
4462}
4463
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004464/// parseDirectiveReq
4465/// ::= name .req registername
4466bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004467 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004468 Parser.Lex(); // Eat the '.req' token.
4469 SMLoc SRegLoc = getLoc();
4470 unsigned RegNum = tryParseRegister();
4471 bool IsVector = false;
4472
4473 if (RegNum == static_cast<unsigned>(-1)) {
4474 StringRef Kind;
4475 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004476 if (!Kind.empty())
4477 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004478 IsVector = true;
4479 }
4480
Nirav Dave2364748a2016-09-16 18:30:20 +00004481 if (RegNum == static_cast<unsigned>(-1))
4482 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004483
4484 // Shouldn't be anything else.
Nirav Dave2364748a2016-09-16 18:30:20 +00004485 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
4486 return Error(Parser.getTok().getLoc(),
4487 "unexpected input in .req directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004488
4489 Parser.Lex(); // Consume the EndOfStatement
4490
4491 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004492 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004493 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4494
Nirav Dave2364748a2016-09-16 18:30:20 +00004495 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004496}
4497
4498/// parseDirectiveUneq
4499/// ::= .unreq registername
4500bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004501 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004502 if (Parser.getTok().isNot(AsmToken::Identifier)) {
4503 Error(Parser.getTok().getLoc(), "unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004504 return false;
4505 }
4506 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4507 Parser.Lex(); // Eat the identifier.
4508 return false;
4509}
4510
Tim Northover3b0846e2014-05-24 12:50:23 +00004511bool
4512AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4513 AArch64MCExpr::VariantKind &ELFRefKind,
4514 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4515 int64_t &Addend) {
4516 ELFRefKind = AArch64MCExpr::VK_INVALID;
4517 DarwinRefKind = MCSymbolRefExpr::VK_None;
4518 Addend = 0;
4519
4520 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4521 ELFRefKind = AE->getKind();
4522 Expr = AE->getSubExpr();
4523 }
4524
4525 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4526 if (SE) {
4527 // It's a simple symbol reference with no addend.
4528 DarwinRefKind = SE->getKind();
4529 return true;
4530 }
4531
4532 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4533 if (!BE)
4534 return false;
4535
4536 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4537 if (!SE)
4538 return false;
4539 DarwinRefKind = SE->getKind();
4540
4541 if (BE->getOpcode() != MCBinaryExpr::Add &&
4542 BE->getOpcode() != MCBinaryExpr::Sub)
4543 return false;
4544
4545 // See if the addend is is a constant, otherwise there's more going
4546 // on here than we can deal with.
4547 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4548 if (!AddendExpr)
4549 return false;
4550
4551 Addend = AddendExpr->getValue();
4552 if (BE->getOpcode() == MCBinaryExpr::Sub)
4553 Addend = -Addend;
4554
4555 // It's some symbol reference + a constant addend, but really
4556 // shouldn't use both Darwin and ELF syntax.
4557 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4558 DarwinRefKind == MCSymbolRefExpr::VK_None;
4559}
4560
4561/// Force static initialization.
4562extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004563 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4564 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4565 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004566}
4567
4568#define GET_REGISTER_MATCHER
4569#define GET_SUBTARGET_FEATURE_NAME
4570#define GET_MATCHER_IMPLEMENTATION
4571#include "AArch64GenAsmMatcher.inc"
4572
4573// Define this matcher function after the auto-generated include so we
4574// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004575unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004576 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004577 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004578 // If the kind is a token for a literal immediate, check if our asm
4579 // operand matches. This is for InstAliases which have a fixed-value
4580 // immediate in the syntax.
4581 int64_t ExpectedVal;
4582 switch (Kind) {
4583 default:
4584 return Match_InvalidOperand;
4585 case MCK__35_0:
4586 ExpectedVal = 0;
4587 break;
4588 case MCK__35_1:
4589 ExpectedVal = 1;
4590 break;
4591 case MCK__35_12:
4592 ExpectedVal = 12;
4593 break;
4594 case MCK__35_16:
4595 ExpectedVal = 16;
4596 break;
4597 case MCK__35_2:
4598 ExpectedVal = 2;
4599 break;
4600 case MCK__35_24:
4601 ExpectedVal = 24;
4602 break;
4603 case MCK__35_3:
4604 ExpectedVal = 3;
4605 break;
4606 case MCK__35_32:
4607 ExpectedVal = 32;
4608 break;
4609 case MCK__35_4:
4610 ExpectedVal = 4;
4611 break;
4612 case MCK__35_48:
4613 ExpectedVal = 48;
4614 break;
4615 case MCK__35_6:
4616 ExpectedVal = 6;
4617 break;
4618 case MCK__35_64:
4619 ExpectedVal = 64;
4620 break;
4621 case MCK__35_8:
4622 ExpectedVal = 8;
4623 break;
4624 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004625 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004627 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 if (!CE)
4629 return Match_InvalidOperand;
4630 if (CE->getValue() == ExpectedVal)
4631 return Match_Success;
4632 return Match_InvalidOperand;
4633}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004634
4635
4636AArch64AsmParser::OperandMatchResultTy
4637AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4638
4639 SMLoc S = getLoc();
4640
4641 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4642 Error(S, "expected register");
4643 return MatchOperand_ParseFail;
4644 }
4645
4646 int FirstReg = tryParseRegister();
4647 if (FirstReg == -1) {
4648 return MatchOperand_ParseFail;
4649 }
4650 const MCRegisterClass &WRegClass =
4651 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4652 const MCRegisterClass &XRegClass =
4653 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4654
4655 bool isXReg = XRegClass.contains(FirstReg),
4656 isWReg = WRegClass.contains(FirstReg);
4657 if (!isXReg && !isWReg) {
4658 Error(S, "expected first even register of a "
4659 "consecutive same-size even/odd register pair");
4660 return MatchOperand_ParseFail;
4661 }
4662
4663 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4664 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4665
4666 if (FirstEncoding & 0x1) {
4667 Error(S, "expected first even register of a "
4668 "consecutive same-size even/odd register pair");
4669 return MatchOperand_ParseFail;
4670 }
4671
4672 SMLoc M = getLoc();
4673 if (getParser().getTok().isNot(AsmToken::Comma)) {
4674 Error(M, "expected comma");
4675 return MatchOperand_ParseFail;
4676 }
4677 // Eat the comma
4678 getParser().Lex();
4679
4680 SMLoc E = getLoc();
4681 int SecondReg = tryParseRegister();
4682 if (SecondReg ==-1) {
4683 return MatchOperand_ParseFail;
4684 }
4685
4686 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
4687 (isXReg && !XRegClass.contains(SecondReg)) ||
4688 (isWReg && !WRegClass.contains(SecondReg))) {
4689 Error(E,"expected second odd register of a "
4690 "consecutive same-size even/odd register pair");
4691 return MatchOperand_ParseFail;
4692 }
4693
4694 unsigned Pair = 0;
4695 if(isXReg) {
4696 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4697 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4698 } else {
4699 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4700 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4701 }
4702
4703 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4704 getContext()));
4705
4706 return MatchOperand_Success;
4707}