blob: 4e438cd552695d02bb06e97cca31f4e2eec636d0 [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 };
Joel Jones504bf332016-10-24 13:37:13 +0000122 bool IsILP32;
Akira Hatanakab11ef082015-11-14 06:35:56 +0000123 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000124 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000125 : MCTargetAsmParser(Options, STI) {
Joel Jones504bf332016-10-24 13:37:13 +0000126 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000127 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000128 MCStreamer &S = getParser().getStreamer();
129 if (S.getTargetStreamer() == nullptr)
130 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000131
132 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000133 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000134 }
135
136 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
137 SMLoc NameLoc, OperandVector &Operands) override;
138 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
139 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000140 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000141 unsigned Kind) override;
142
143 static bool classifySymbolRef(const MCExpr *Expr,
144 AArch64MCExpr::VariantKind &ELFRefKind,
145 MCSymbolRefExpr::VariantKind &DarwinRefKind,
146 int64_t &Addend);
147};
148} // end anonymous namespace
149
150namespace {
151
152/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
153/// instruction.
154class AArch64Operand : public MCParsedAsmOperand {
155private:
156 enum KindTy {
157 k_Immediate,
158 k_ShiftedImm,
159 k_CondCode,
160 k_Register,
161 k_VectorList,
162 k_VectorIndex,
163 k_Token,
164 k_SysReg,
165 k_SysCR,
166 k_Prefetch,
167 k_ShiftExtend,
168 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000169 k_Barrier,
170 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000171 } Kind;
172
173 SMLoc StartLoc, EndLoc;
174
175 struct TokOp {
176 const char *Data;
177 unsigned Length;
178 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
179 };
180
181 struct RegOp {
182 unsigned RegNum;
183 bool isVector;
184 };
185
186 struct VectorListOp {
187 unsigned RegNum;
188 unsigned Count;
189 unsigned NumElements;
190 unsigned ElementKind;
191 };
192
193 struct VectorIndexOp {
194 unsigned Val;
195 };
196
197 struct ImmOp {
198 const MCExpr *Val;
199 };
200
201 struct ShiftedImmOp {
202 const MCExpr *Val;
203 unsigned ShiftAmount;
204 };
205
206 struct CondCodeOp {
207 AArch64CC::CondCode Code;
208 };
209
210 struct FPImmOp {
211 unsigned Val; // Encoded 8-bit representation.
212 };
213
214 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000215 const char *Data;
216 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000217 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000218 };
219
220 struct SysRegOp {
221 const char *Data;
222 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000223 uint32_t MRSReg;
224 uint32_t MSRReg;
225 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000226 };
227
228 struct SysCRImmOp {
229 unsigned Val;
230 };
231
232 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000233 const char *Data;
234 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000235 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000236 };
237
Oliver Stannarda34e4702015-12-01 10:48:51 +0000238 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000239 const char *Data;
240 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000241 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000242 };
243
Tim Northover3b0846e2014-05-24 12:50:23 +0000244 struct ShiftExtendOp {
245 AArch64_AM::ShiftExtendType Type;
246 unsigned Amount;
247 bool HasExplicitAmount;
248 };
249
250 struct ExtendOp {
251 unsigned Val;
252 };
253
254 union {
255 struct TokOp Tok;
256 struct RegOp Reg;
257 struct VectorListOp VectorList;
258 struct VectorIndexOp VectorIndex;
259 struct ImmOp Imm;
260 struct ShiftedImmOp ShiftedImm;
261 struct CondCodeOp CondCode;
262 struct FPImmOp FPImm;
263 struct BarrierOp Barrier;
264 struct SysRegOp SysReg;
265 struct SysCRImmOp SysCRImm;
266 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000267 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000268 struct ShiftExtendOp ShiftExtend;
269 };
270
271 // Keep the MCContext around as the MCExprs may need manipulated during
272 // the add<>Operands() calls.
273 MCContext &Ctx;
274
David Blaikie960ea3f2014-06-08 16:18:35 +0000275public:
David Blaikie9f380a32015-03-16 18:06:57 +0000276 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000277
Tim Northover3b0846e2014-05-24 12:50:23 +0000278 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
279 Kind = o.Kind;
280 StartLoc = o.StartLoc;
281 EndLoc = o.EndLoc;
282 switch (Kind) {
283 case k_Token:
284 Tok = o.Tok;
285 break;
286 case k_Immediate:
287 Imm = o.Imm;
288 break;
289 case k_ShiftedImm:
290 ShiftedImm = o.ShiftedImm;
291 break;
292 case k_CondCode:
293 CondCode = o.CondCode;
294 break;
295 case k_FPImm:
296 FPImm = o.FPImm;
297 break;
298 case k_Barrier:
299 Barrier = o.Barrier;
300 break;
301 case k_Register:
302 Reg = o.Reg;
303 break;
304 case k_VectorList:
305 VectorList = o.VectorList;
306 break;
307 case k_VectorIndex:
308 VectorIndex = o.VectorIndex;
309 break;
310 case k_SysReg:
311 SysReg = o.SysReg;
312 break;
313 case k_SysCR:
314 SysCRImm = o.SysCRImm;
315 break;
316 case k_Prefetch:
317 Prefetch = o.Prefetch;
318 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000319 case k_PSBHint:
320 PSBHint = o.PSBHint;
321 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000322 case k_ShiftExtend:
323 ShiftExtend = o.ShiftExtend;
324 break;
325 }
326 }
327
328 /// getStartLoc - Get the location of the first token of this operand.
329 SMLoc getStartLoc() const override { return StartLoc; }
330 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000331 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000332
333 StringRef getToken() const {
334 assert(Kind == k_Token && "Invalid access!");
335 return StringRef(Tok.Data, Tok.Length);
336 }
337
338 bool isTokenSuffix() const {
339 assert(Kind == k_Token && "Invalid access!");
340 return Tok.IsSuffix;
341 }
342
343 const MCExpr *getImm() const {
344 assert(Kind == k_Immediate && "Invalid access!");
345 return Imm.Val;
346 }
347
348 const MCExpr *getShiftedImmVal() const {
349 assert(Kind == k_ShiftedImm && "Invalid access!");
350 return ShiftedImm.Val;
351 }
352
353 unsigned getShiftedImmShift() const {
354 assert(Kind == k_ShiftedImm && "Invalid access!");
355 return ShiftedImm.ShiftAmount;
356 }
357
358 AArch64CC::CondCode getCondCode() const {
359 assert(Kind == k_CondCode && "Invalid access!");
360 return CondCode.Code;
361 }
362
363 unsigned getFPImm() const {
364 assert(Kind == k_FPImm && "Invalid access!");
365 return FPImm.Val;
366 }
367
368 unsigned getBarrier() const {
369 assert(Kind == k_Barrier && "Invalid access!");
370 return Barrier.Val;
371 }
372
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000373 StringRef getBarrierName() const {
374 assert(Kind == k_Barrier && "Invalid access!");
375 return StringRef(Barrier.Data, Barrier.Length);
376 }
377
Tim Northover3b0846e2014-05-24 12:50:23 +0000378 unsigned getReg() const override {
379 assert(Kind == k_Register && "Invalid access!");
380 return Reg.RegNum;
381 }
382
383 unsigned getVectorListStart() const {
384 assert(Kind == k_VectorList && "Invalid access!");
385 return VectorList.RegNum;
386 }
387
388 unsigned getVectorListCount() const {
389 assert(Kind == k_VectorList && "Invalid access!");
390 return VectorList.Count;
391 }
392
393 unsigned getVectorIndex() const {
394 assert(Kind == k_VectorIndex && "Invalid access!");
395 return VectorIndex.Val;
396 }
397
398 StringRef getSysReg() const {
399 assert(Kind == k_SysReg && "Invalid access!");
400 return StringRef(SysReg.Data, SysReg.Length);
401 }
402
Tim Northover3b0846e2014-05-24 12:50:23 +0000403 unsigned getSysCR() const {
404 assert(Kind == k_SysCR && "Invalid access!");
405 return SysCRImm.Val;
406 }
407
408 unsigned getPrefetch() const {
409 assert(Kind == k_Prefetch && "Invalid access!");
410 return Prefetch.Val;
411 }
412
Oliver Stannarda34e4702015-12-01 10:48:51 +0000413 unsigned getPSBHint() const {
414 assert(Kind == k_PSBHint && "Invalid access!");
415 return PSBHint.Val;
416 }
417
418 StringRef getPSBHintName() const {
419 assert(Kind == k_PSBHint && "Invalid access!");
420 return StringRef(PSBHint.Data, PSBHint.Length);
421 }
422
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000423 StringRef getPrefetchName() const {
424 assert(Kind == k_Prefetch && "Invalid access!");
425 return StringRef(Prefetch.Data, Prefetch.Length);
426 }
427
Tim Northover3b0846e2014-05-24 12:50:23 +0000428 AArch64_AM::ShiftExtendType getShiftExtendType() const {
429 assert(Kind == k_ShiftExtend && "Invalid access!");
430 return ShiftExtend.Type;
431 }
432
433 unsigned getShiftExtendAmount() const {
434 assert(Kind == k_ShiftExtend && "Invalid access!");
435 return ShiftExtend.Amount;
436 }
437
438 bool hasShiftExtendAmount() const {
439 assert(Kind == k_ShiftExtend && "Invalid access!");
440 return ShiftExtend.HasExplicitAmount;
441 }
442
443 bool isImm() const override { return Kind == k_Immediate; }
444 bool isMem() const override { return false; }
445 bool isSImm9() const {
446 if (!isImm())
447 return false;
448 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
449 if (!MCE)
450 return false;
451 int64_t Val = MCE->getValue();
452 return (Val >= -256 && Val < 256);
453 }
454 bool isSImm7s4() const {
455 if (!isImm())
456 return false;
457 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
458 if (!MCE)
459 return false;
460 int64_t Val = MCE->getValue();
461 return (Val >= -256 && Val <= 252 && (Val & 3) == 0);
462 }
463 bool isSImm7s8() const {
464 if (!isImm())
465 return false;
466 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
467 if (!MCE)
468 return false;
469 int64_t Val = MCE->getValue();
470 return (Val >= -512 && Val <= 504 && (Val & 7) == 0);
471 }
472 bool isSImm7s16() const {
473 if (!isImm())
474 return false;
475 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
476 if (!MCE)
477 return false;
478 int64_t Val = MCE->getValue();
479 return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
480 }
481
482 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
483 AArch64MCExpr::VariantKind ELFRefKind;
484 MCSymbolRefExpr::VariantKind DarwinRefKind;
485 int64_t Addend;
486 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
487 Addend)) {
488 // If we don't understand the expression, assume the best and
489 // let the fixup and relocation code deal with it.
490 return true;
491 }
492
493 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
494 ELFRefKind == AArch64MCExpr::VK_LO12 ||
495 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
496 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
497 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
498 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
499 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
500 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
501 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
502 // Note that we don't range-check the addend. It's adjusted modulo page
503 // size when converted, so there is no "out of range" condition when using
504 // @pageoff.
505 return Addend >= 0 && (Addend % Scale) == 0;
506 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
507 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
508 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
509 return Addend == 0;
510 }
511
512 return false;
513 }
514
515 template <int Scale> bool isUImm12Offset() const {
516 if (!isImm())
517 return false;
518
519 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
520 if (!MCE)
521 return isSymbolicUImm12Offset(getImm(), Scale);
522
523 int64_t Val = MCE->getValue();
524 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
525 }
526
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000527 bool isImm0_1() const {
528 if (!isImm())
529 return false;
530 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
531 if (!MCE)
532 return false;
533 int64_t Val = MCE->getValue();
534 return (Val >= 0 && Val < 2);
535 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000536 bool isImm0_7() const {
537 if (!isImm())
538 return false;
539 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
540 if (!MCE)
541 return false;
542 int64_t Val = MCE->getValue();
543 return (Val >= 0 && Val < 8);
544 }
545 bool isImm1_8() const {
546 if (!isImm())
547 return false;
548 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
549 if (!MCE)
550 return false;
551 int64_t Val = MCE->getValue();
552 return (Val > 0 && Val < 9);
553 }
554 bool isImm0_15() const {
555 if (!isImm())
556 return false;
557 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
558 if (!MCE)
559 return false;
560 int64_t Val = MCE->getValue();
561 return (Val >= 0 && Val < 16);
562 }
563 bool isImm1_16() const {
564 if (!isImm())
565 return false;
566 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
567 if (!MCE)
568 return false;
569 int64_t Val = MCE->getValue();
570 return (Val > 0 && Val < 17);
571 }
572 bool isImm0_31() const {
573 if (!isImm())
574 return false;
575 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
576 if (!MCE)
577 return false;
578 int64_t Val = MCE->getValue();
579 return (Val >= 0 && Val < 32);
580 }
581 bool isImm1_31() const {
582 if (!isImm())
583 return false;
584 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
585 if (!MCE)
586 return false;
587 int64_t Val = MCE->getValue();
588 return (Val >= 1 && Val < 32);
589 }
590 bool isImm1_32() const {
591 if (!isImm())
592 return false;
593 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
594 if (!MCE)
595 return false;
596 int64_t Val = MCE->getValue();
597 return (Val >= 1 && Val < 33);
598 }
599 bool isImm0_63() const {
600 if (!isImm())
601 return false;
602 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
603 if (!MCE)
604 return false;
605 int64_t Val = MCE->getValue();
606 return (Val >= 0 && Val < 64);
607 }
608 bool isImm1_63() const {
609 if (!isImm())
610 return false;
611 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
612 if (!MCE)
613 return false;
614 int64_t Val = MCE->getValue();
615 return (Val >= 1 && Val < 64);
616 }
617 bool isImm1_64() const {
618 if (!isImm())
619 return false;
620 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
621 if (!MCE)
622 return false;
623 int64_t Val = MCE->getValue();
624 return (Val >= 1 && Val < 65);
625 }
626 bool isImm0_127() const {
627 if (!isImm())
628 return false;
629 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
630 if (!MCE)
631 return false;
632 int64_t Val = MCE->getValue();
633 return (Val >= 0 && Val < 128);
634 }
635 bool isImm0_255() const {
636 if (!isImm())
637 return false;
638 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
639 if (!MCE)
640 return false;
641 int64_t Val = MCE->getValue();
642 return (Val >= 0 && Val < 256);
643 }
644 bool isImm0_65535() const {
645 if (!isImm())
646 return false;
647 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
648 if (!MCE)
649 return false;
650 int64_t Val = MCE->getValue();
651 return (Val >= 0 && Val < 65536);
652 }
653 bool isImm32_63() const {
654 if (!isImm())
655 return false;
656 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
657 if (!MCE)
658 return false;
659 int64_t Val = MCE->getValue();
660 return (Val >= 32 && Val < 64);
661 }
662 bool isLogicalImm32() const {
663 if (!isImm())
664 return false;
665 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
666 if (!MCE)
667 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000668 int64_t Val = MCE->getValue();
669 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
670 return false;
671 Val &= 0xFFFFFFFF;
672 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000673 }
674 bool isLogicalImm64() const {
675 if (!isImm())
676 return false;
677 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
678 if (!MCE)
679 return false;
680 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
681 }
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000682 bool isLogicalImm32Not() const {
683 if (!isImm())
684 return false;
685 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
686 if (!MCE)
687 return false;
688 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
689 return AArch64_AM::isLogicalImmediate(Val, 32);
690 }
691 bool isLogicalImm64Not() const {
692 if (!isImm())
693 return false;
694 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
695 if (!MCE)
696 return false;
697 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
698 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000699 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
700 bool isAddSubImm() const {
701 if (!isShiftedImm() && !isImm())
702 return false;
703
704 const MCExpr *Expr;
705
706 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
707 if (isShiftedImm()) {
708 unsigned Shift = ShiftedImm.ShiftAmount;
709 Expr = ShiftedImm.Val;
710 if (Shift != 0 && Shift != 12)
711 return false;
712 } else {
713 Expr = getImm();
714 }
715
716 AArch64MCExpr::VariantKind ELFRefKind;
717 MCSymbolRefExpr::VariantKind DarwinRefKind;
718 int64_t Addend;
719 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
720 DarwinRefKind, Addend)) {
721 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
722 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
723 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
724 || ELFRefKind == AArch64MCExpr::VK_LO12
725 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
726 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
727 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
728 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
729 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
730 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
731 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
732 }
733
Diana Picusc93518d2016-10-11 09:17:47 +0000734 // If it's a constant, it should be a real immediate in range:
735 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
736 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
737
738 // If it's an expression, we hope for the best and let the fixup/relocation
739 // code deal with it.
740 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000741 }
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000742 bool isAddSubImmNeg() const {
743 if (!isShiftedImm() && !isImm())
744 return false;
745
746 const MCExpr *Expr;
747
748 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
749 if (isShiftedImm()) {
750 unsigned Shift = ShiftedImm.ShiftAmount;
751 Expr = ShiftedImm.Val;
752 if (Shift != 0 && Shift != 12)
753 return false;
754 } else
755 Expr = getImm();
756
757 // Otherwise it should be a real negative immediate in range:
758 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
759 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
760 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000761 bool isCondCode() const { return Kind == k_CondCode; }
762 bool isSIMDImmType10() const {
763 if (!isImm())
764 return false;
765 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
766 if (!MCE)
767 return false;
768 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
769 }
770 bool isBranchTarget26() const {
771 if (!isImm())
772 return false;
773 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
774 if (!MCE)
775 return true;
776 int64_t Val = MCE->getValue();
777 if (Val & 0x3)
778 return false;
779 return (Val >= -(0x2000000 << 2) && Val <= (0x1ffffff << 2));
780 }
781 bool isPCRelLabel19() const {
782 if (!isImm())
783 return false;
784 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
785 if (!MCE)
786 return true;
787 int64_t Val = MCE->getValue();
788 if (Val & 0x3)
789 return false;
790 return (Val >= -(0x40000 << 2) && Val <= (0x3ffff << 2));
791 }
792 bool isBranchTarget14() const {
793 if (!isImm())
794 return false;
795 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
796 if (!MCE)
797 return true;
798 int64_t Val = MCE->getValue();
799 if (Val & 0x3)
800 return false;
801 return (Val >= -(0x2000 << 2) && Val <= (0x1fff << 2));
802 }
803
804 bool
805 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
806 if (!isImm())
807 return false;
808
809 AArch64MCExpr::VariantKind ELFRefKind;
810 MCSymbolRefExpr::VariantKind DarwinRefKind;
811 int64_t Addend;
812 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
813 DarwinRefKind, Addend)) {
814 return false;
815 }
816 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
817 return false;
818
819 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
820 if (ELFRefKind == AllowedModifiers[i])
821 return Addend == 0;
822 }
823
824 return false;
825 }
826
827 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000828 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000829 }
830
831 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000832 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
833 AArch64MCExpr::VK_TPREL_G2,
834 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000835 }
836
837 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000838 return isMovWSymbol({
839 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000840 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
841 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000842 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000843 }
844
845 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000846 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
847 AArch64MCExpr::VK_TPREL_G0,
848 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000849 }
850
851 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000852 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000853 }
854
855 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000856 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000857 }
858
859 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000860 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
861 AArch64MCExpr::VK_TPREL_G1_NC,
862 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000863 }
864
865 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000866 return isMovWSymbol(
867 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
868 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000869 }
870
871 template<int RegWidth, int Shift>
872 bool isMOVZMovAlias() const {
873 if (!isImm()) return false;
874
875 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
876 if (!CE) return false;
877 uint64_t Value = CE->getValue();
878
Tim Northoverdaa1c012016-06-16 01:42:25 +0000879 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000880 }
881
882 template<int RegWidth, int Shift>
883 bool isMOVNMovAlias() const {
884 if (!isImm()) return false;
885
886 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
887 if (!CE) return false;
888 uint64_t Value = CE->getValue();
889
Tim Northoverdaa1c012016-06-16 01:42:25 +0000890 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000891 }
892
893 bool isFPImm() const { return Kind == k_FPImm; }
894 bool isBarrier() const { return Kind == k_Barrier; }
895 bool isSysReg() const { return Kind == k_SysReg; }
896 bool isMRSSystemRegister() const {
897 if (!isSysReg()) return false;
898
Tim Northover7cd58932015-01-22 17:23:04 +0000899 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000900 }
901 bool isMSRSystemRegister() const {
902 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000903 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000904 }
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000905 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000906 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000907 return (SysReg.PStateField == AArch64PState::PAN ||
908 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000909 }
910 bool isSystemPStateFieldWithImm0_15() const {
911 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000912 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000913 }
914 bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
915 bool isVectorReg() const { return Kind == k_Register && Reg.isVector; }
916 bool isVectorRegLo() const {
917 return Kind == k_Register && Reg.isVector &&
918 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
919 Reg.RegNum);
920 }
921 bool isGPR32as64() const {
922 return Kind == k_Register && !Reg.isVector &&
923 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
924 }
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000925 bool isWSeqPair() const {
926 return Kind == k_Register && !Reg.isVector &&
927 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
928 Reg.RegNum);
929 }
930 bool isXSeqPair() const {
931 return Kind == k_Register && !Reg.isVector &&
932 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
933 Reg.RegNum);
934 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000935
936 bool isGPR64sp0() const {
937 return Kind == k_Register && !Reg.isVector &&
938 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
939 }
940
941 /// Is this a vector list with the type implicit (presumably attached to the
942 /// instruction itself)?
943 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
944 return Kind == k_VectorList && VectorList.Count == NumRegs &&
945 !VectorList.ElementKind;
946 }
947
948 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
949 bool isTypedVectorList() const {
950 if (Kind != k_VectorList)
951 return false;
952 if (VectorList.Count != NumRegs)
953 return false;
954 if (VectorList.ElementKind != ElementKind)
955 return false;
956 return VectorList.NumElements == NumElements;
957 }
958
959 bool isVectorIndex1() const {
960 return Kind == k_VectorIndex && VectorIndex.Val == 1;
961 }
962 bool isVectorIndexB() const {
963 return Kind == k_VectorIndex && VectorIndex.Val < 16;
964 }
965 bool isVectorIndexH() const {
966 return Kind == k_VectorIndex && VectorIndex.Val < 8;
967 }
968 bool isVectorIndexS() const {
969 return Kind == k_VectorIndex && VectorIndex.Val < 4;
970 }
971 bool isVectorIndexD() const {
972 return Kind == k_VectorIndex && VectorIndex.Val < 2;
973 }
974 bool isToken() const override { return Kind == k_Token; }
975 bool isTokenEqual(StringRef Str) const {
976 return Kind == k_Token && getToken() == Str;
977 }
978 bool isSysCR() const { return Kind == k_SysCR; }
979 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000980 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000981 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
982 bool isShifter() const {
983 if (!isShiftExtend())
984 return false;
985
986 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
987 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
988 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
989 ST == AArch64_AM::MSL);
990 }
991 bool isExtend() const {
992 if (!isShiftExtend())
993 return false;
994
995 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
996 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
997 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
998 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
999 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1000 ET == AArch64_AM::LSL) &&
1001 getShiftExtendAmount() <= 4;
1002 }
1003
1004 bool isExtend64() const {
1005 if (!isExtend())
1006 return false;
1007 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1008 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1009 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1010 }
1011 bool isExtendLSL64() const {
1012 if (!isExtend())
1013 return false;
1014 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1015 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1016 ET == AArch64_AM::LSL) &&
1017 getShiftExtendAmount() <= 4;
1018 }
1019
1020 template<int Width> bool isMemXExtend() const {
1021 if (!isExtend())
1022 return false;
1023 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1024 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1025 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1026 getShiftExtendAmount() == 0);
1027 }
1028
1029 template<int Width> bool isMemWExtend() const {
1030 if (!isExtend())
1031 return false;
1032 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1033 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1034 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1035 getShiftExtendAmount() == 0);
1036 }
1037
1038 template <unsigned width>
1039 bool isArithmeticShifter() const {
1040 if (!isShifter())
1041 return false;
1042
1043 // An arithmetic shifter is LSL, LSR, or ASR.
1044 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1045 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1046 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1047 }
1048
1049 template <unsigned width>
1050 bool isLogicalShifter() const {
1051 if (!isShifter())
1052 return false;
1053
1054 // A logical shifter is LSL, LSR, ASR or ROR.
1055 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1056 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1057 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1058 getShiftExtendAmount() < width;
1059 }
1060
1061 bool isMovImm32Shifter() const {
1062 if (!isShifter())
1063 return false;
1064
1065 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1066 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1067 if (ST != AArch64_AM::LSL)
1068 return false;
1069 uint64_t Val = getShiftExtendAmount();
1070 return (Val == 0 || Val == 16);
1071 }
1072
1073 bool isMovImm64Shifter() const {
1074 if (!isShifter())
1075 return false;
1076
1077 // A MOVi shifter is LSL of 0 or 16.
1078 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1079 if (ST != AArch64_AM::LSL)
1080 return false;
1081 uint64_t Val = getShiftExtendAmount();
1082 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1083 }
1084
1085 bool isLogicalVecShifter() const {
1086 if (!isShifter())
1087 return false;
1088
1089 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1090 unsigned Shift = getShiftExtendAmount();
1091 return getShiftExtendType() == AArch64_AM::LSL &&
1092 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1093 }
1094
1095 bool isLogicalVecHalfWordShifter() const {
1096 if (!isLogicalVecShifter())
1097 return false;
1098
1099 // A logical vector shifter is a left shift by 0 or 8.
1100 unsigned Shift = getShiftExtendAmount();
1101 return getShiftExtendType() == AArch64_AM::LSL &&
1102 (Shift == 0 || Shift == 8);
1103 }
1104
1105 bool isMoveVecShifter() const {
1106 if (!isShiftExtend())
1107 return false;
1108
1109 // A logical vector shifter is a left shift by 8 or 16.
1110 unsigned Shift = getShiftExtendAmount();
1111 return getShiftExtendType() == AArch64_AM::MSL &&
1112 (Shift == 8 || Shift == 16);
1113 }
1114
1115 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1116 // to LDUR/STUR when the offset is not legal for the former but is for
1117 // the latter. As such, in addition to checking for being a legal unscaled
1118 // address, also check that it is not a legal scaled address. This avoids
1119 // ambiguity in the matcher.
1120 template<int Width>
1121 bool isSImm9OffsetFB() const {
1122 return isSImm9() && !isUImm12Offset<Width / 8>();
1123 }
1124
1125 bool isAdrpLabel() const {
1126 // Validation was handled during parsing, so we just sanity check that
1127 // something didn't go haywire.
1128 if (!isImm())
1129 return false;
1130
1131 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1132 int64_t Val = CE->getValue();
1133 int64_t Min = - (4096 * (1LL << (21 - 1)));
1134 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1135 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1136 }
1137
1138 return true;
1139 }
1140
1141 bool isAdrLabel() const {
1142 // Validation was handled during parsing, so we just sanity check that
1143 // something didn't go haywire.
1144 if (!isImm())
1145 return false;
1146
1147 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1148 int64_t Val = CE->getValue();
1149 int64_t Min = - (1LL << (21 - 1));
1150 int64_t Max = ((1LL << (21 - 1)) - 1);
1151 return Val >= Min && Val <= Max;
1152 }
1153
1154 return true;
1155 }
1156
1157 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1158 // Add as immediates when possible. Null MCExpr = 0.
1159 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001160 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001161 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001162 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001163 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001164 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001165 }
1166
1167 void addRegOperands(MCInst &Inst, unsigned N) const {
1168 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001169 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001170 }
1171
1172 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1173 assert(N == 1 && "Invalid number of operands!");
1174 assert(
1175 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1176
1177 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1178 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1179 RI->getEncodingValue(getReg()));
1180
Jim Grosbache9119e42015-05-13 18:37:00 +00001181 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 }
1183
1184 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 assert(
1187 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001188 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001189 }
1190
1191 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1192 assert(N == 1 && "Invalid number of operands!");
1193 assert(
1194 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001195 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001196 }
1197
1198 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1199 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001200 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001201 }
1202
1203 template <unsigned NumRegs>
1204 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1205 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001206 static const unsigned FirstRegs[] = { AArch64::D0,
1207 AArch64::D0_D1,
1208 AArch64::D0_D1_D2,
1209 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001210 unsigned FirstReg = FirstRegs[NumRegs - 1];
1211
1212 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001213 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001214 }
1215
1216 template <unsigned NumRegs>
1217 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001219 static const unsigned FirstRegs[] = { AArch64::Q0,
1220 AArch64::Q0_Q1,
1221 AArch64::Q0_Q1_Q2,
1222 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001223 unsigned FirstReg = FirstRegs[NumRegs - 1];
1224
1225 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001226 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001227 }
1228
1229 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1230 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001231 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001232 }
1233
1234 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1235 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001236 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001237 }
1238
1239 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1240 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001241 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001242 }
1243
1244 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001246 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001247 }
1248
1249 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001251 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001252 }
1253
1254 void addImmOperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
1256 // If this is a pageoff symrefexpr with an addend, adjust the addend
1257 // to be only the page-offset portion. Otherwise, just add the expr
1258 // as-is.
1259 addExpr(Inst, getImm());
1260 }
1261
1262 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1263 assert(N == 2 && "Invalid number of operands!");
1264 if (isShiftedImm()) {
1265 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001266 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001267 } else {
1268 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001269 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001270 }
1271 }
1272
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001273 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1274 assert(N == 2 && "Invalid number of operands!");
1275
1276 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1277 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1278 int64_t Val = -CE->getValue();
1279 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1280
1281 Inst.addOperand(MCOperand::createImm(Val));
1282 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1283 }
1284
Tim Northover3b0846e2014-05-24 12:50:23 +00001285 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1286 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001287 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001288 }
1289
1290 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1293 if (!MCE)
1294 addExpr(Inst, getImm());
1295 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001296 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001297 }
1298
1299 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1300 addImmOperands(Inst, N);
1301 }
1302
1303 template<int Scale>
1304 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1305 assert(N == 1 && "Invalid number of operands!");
1306 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1307
1308 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001309 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001310 return;
1311 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001312 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001313 }
1314
1315 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001317 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001318 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001319 }
1320
1321 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1322 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001323 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001324 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001325 }
1326
1327 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1328 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001329 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001330 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001331 }
1332
1333 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001335 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001336 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001337 }
1338
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001339 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1340 assert(N == 1 && "Invalid number of operands!");
1341 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1342 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1343 }
1344
Tim Northover3b0846e2014-05-24 12:50:23 +00001345 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1346 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001347 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001348 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001349 }
1350
1351 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1352 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001353 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001354 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001355 }
1356
1357 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1358 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001359 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001360 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001361 }
1362
1363 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001365 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001366 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001367 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001368 }
1369
1370 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001372 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001373 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 }
1375
1376 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1377 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001378 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001379 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001380 }
1381
1382 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1383 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001384 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001385 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001386 }
1387
1388 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001390 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001391 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001392 }
1393
1394 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1395 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001396 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001397 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001398 }
1399
1400 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1401 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001402 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001403 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 }
1405
1406 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001408 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001409 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001410 }
1411
1412 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1413 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001414 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001415 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001416 }
1417
1418 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1419 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001420 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001421 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001422 }
1423
1424 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001426 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001427 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 }
1429
1430 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1431 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001432 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001433 uint64_t encoding =
1434 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001435 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001436 }
1437
1438 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1439 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001440 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001441 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001442 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001443 }
1444
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001445 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 1 && "Invalid number of operands!");
1447 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1448 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1449 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001450 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001451 }
1452
1453 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1456 uint64_t encoding =
1457 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001458 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001459 }
1460
Tim Northover3b0846e2014-05-24 12:50:23 +00001461 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1462 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001463 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001465 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001466 }
1467
1468 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1469 // Branch operands don't encode the low bits, so shift them off
1470 // here. If it's a label, however, just put it on directly as there's
1471 // not enough information now to do anything.
1472 assert(N == 1 && "Invalid number of operands!");
1473 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1474 if (!MCE) {
1475 addExpr(Inst, getImm());
1476 return;
1477 }
1478 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001479 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 }
1481
1482 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1483 // Branch operands don't encode the low bits, so shift them off
1484 // here. If it's a label, however, just put it on directly as there's
1485 // not enough information now to do anything.
1486 assert(N == 1 && "Invalid number of operands!");
1487 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1488 if (!MCE) {
1489 addExpr(Inst, getImm());
1490 return;
1491 }
1492 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001493 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001494 }
1495
1496 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1497 // Branch operands don't encode the low bits, so shift them off
1498 // here. If it's a label, however, just put it on directly as there's
1499 // not enough information now to do anything.
1500 assert(N == 1 && "Invalid number of operands!");
1501 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1502 if (!MCE) {
1503 addExpr(Inst, getImm());
1504 return;
1505 }
1506 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001507 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001508 }
1509
1510 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1511 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001512 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001513 }
1514
1515 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1516 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001517 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001518 }
1519
1520 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
1522
Jim Grosbache9119e42015-05-13 18:37:00 +00001523 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001524 }
1525
1526 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1527 assert(N == 1 && "Invalid number of operands!");
1528
Jim Grosbache9119e42015-05-13 18:37:00 +00001529 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 }
1531
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001532 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534
1535 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1536 }
1537
1538 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001539 assert(N == 1 && "Invalid number of operands!");
1540
Jim Grosbache9119e42015-05-13 18:37:00 +00001541 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001542 }
1543
1544 void addSysCROperands(MCInst &Inst, unsigned N) const {
1545 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001546 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001547 }
1548
1549 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1550 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001551 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001552 }
1553
Oliver Stannarda34e4702015-12-01 10:48:51 +00001554 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1555 assert(N == 1 && "Invalid number of operands!");
1556 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1557 }
1558
Tim Northover3b0846e2014-05-24 12:50:23 +00001559 void addShifterOperands(MCInst &Inst, unsigned N) const {
1560 assert(N == 1 && "Invalid number of operands!");
1561 unsigned Imm =
1562 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001563 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001564 }
1565
1566 void addExtendOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 1 && "Invalid number of operands!");
1568 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1569 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1570 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001571 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 }
1573
1574 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1575 assert(N == 1 && "Invalid number of operands!");
1576 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1577 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1578 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001579 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001580 }
1581
1582 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 2 && "Invalid number of operands!");
1584 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1585 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001586 Inst.addOperand(MCOperand::createImm(IsSigned));
1587 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001588 }
1589
1590 // For 8-bit load/store instructions with a register offset, both the
1591 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1592 // they're disambiguated by whether the shift was explicit or implicit rather
1593 // than its size.
1594 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1595 assert(N == 2 && "Invalid number of operands!");
1596 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1597 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001598 Inst.addOperand(MCOperand::createImm(IsSigned));
1599 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 }
1601
1602 template<int Shift>
1603 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1604 assert(N == 1 && "Invalid number of operands!");
1605
1606 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1607 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001608 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001609 }
1610
1611 template<int Shift>
1612 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1613 assert(N == 1 && "Invalid number of operands!");
1614
1615 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1616 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001617 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001618 }
1619
1620 void print(raw_ostream &OS) const override;
1621
David Blaikie960ea3f2014-06-08 16:18:35 +00001622 static std::unique_ptr<AArch64Operand>
1623 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1624 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001625 Op->Tok.Data = Str.data();
1626 Op->Tok.Length = Str.size();
1627 Op->Tok.IsSuffix = IsSuffix;
1628 Op->StartLoc = S;
1629 Op->EndLoc = S;
1630 return Op;
1631 }
1632
David Blaikie960ea3f2014-06-08 16:18:35 +00001633 static std::unique_ptr<AArch64Operand>
1634 CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
1635 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001636 Op->Reg.RegNum = RegNum;
1637 Op->Reg.isVector = isVector;
1638 Op->StartLoc = S;
1639 Op->EndLoc = E;
1640 return Op;
1641 }
1642
David Blaikie960ea3f2014-06-08 16:18:35 +00001643 static std::unique_ptr<AArch64Operand>
1644 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1645 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1646 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001647 Op->VectorList.RegNum = RegNum;
1648 Op->VectorList.Count = Count;
1649 Op->VectorList.NumElements = NumElements;
1650 Op->VectorList.ElementKind = ElementKind;
1651 Op->StartLoc = S;
1652 Op->EndLoc = E;
1653 return Op;
1654 }
1655
David Blaikie960ea3f2014-06-08 16:18:35 +00001656 static std::unique_ptr<AArch64Operand>
1657 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1658 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001659 Op->VectorIndex.Val = Idx;
1660 Op->StartLoc = S;
1661 Op->EndLoc = E;
1662 return Op;
1663 }
1664
David Blaikie960ea3f2014-06-08 16:18:35 +00001665 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1666 SMLoc E, MCContext &Ctx) {
1667 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001668 Op->Imm.Val = Val;
1669 Op->StartLoc = S;
1670 Op->EndLoc = E;
1671 return Op;
1672 }
1673
David Blaikie960ea3f2014-06-08 16:18:35 +00001674 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1675 unsigned ShiftAmount,
1676 SMLoc S, SMLoc E,
1677 MCContext &Ctx) {
1678 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001679 Op->ShiftedImm .Val = Val;
1680 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1681 Op->StartLoc = S;
1682 Op->EndLoc = E;
1683 return Op;
1684 }
1685
David Blaikie960ea3f2014-06-08 16:18:35 +00001686 static std::unique_ptr<AArch64Operand>
1687 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1688 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001689 Op->CondCode.Code = Code;
1690 Op->StartLoc = S;
1691 Op->EndLoc = E;
1692 return Op;
1693 }
1694
David Blaikie960ea3f2014-06-08 16:18:35 +00001695 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1696 MCContext &Ctx) {
1697 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001698 Op->FPImm.Val = Val;
1699 Op->StartLoc = S;
1700 Op->EndLoc = S;
1701 return Op;
1702 }
1703
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001704 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1705 StringRef Str,
1706 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001707 MCContext &Ctx) {
1708 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001709 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001710 Op->Barrier.Data = Str.data();
1711 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001712 Op->StartLoc = S;
1713 Op->EndLoc = S;
1714 return Op;
1715 }
1716
Tim Northover7cd58932015-01-22 17:23:04 +00001717 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1718 uint32_t MRSReg,
1719 uint32_t MSRReg,
1720 uint32_t PStateField,
1721 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001722 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001723 Op->SysReg.Data = Str.data();
1724 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001725 Op->SysReg.MRSReg = MRSReg;
1726 Op->SysReg.MSRReg = MSRReg;
1727 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001728 Op->StartLoc = S;
1729 Op->EndLoc = S;
1730 return Op;
1731 }
1732
David Blaikie960ea3f2014-06-08 16:18:35 +00001733 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1734 SMLoc E, MCContext &Ctx) {
1735 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001736 Op->SysCRImm.Val = Val;
1737 Op->StartLoc = S;
1738 Op->EndLoc = E;
1739 return Op;
1740 }
1741
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001742 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1743 StringRef Str,
1744 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001745 MCContext &Ctx) {
1746 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001747 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001748 Op->Barrier.Data = Str.data();
1749 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001750 Op->StartLoc = S;
1751 Op->EndLoc = S;
1752 return Op;
1753 }
1754
Oliver Stannarda34e4702015-12-01 10:48:51 +00001755 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1756 StringRef Str,
1757 SMLoc S,
1758 MCContext &Ctx) {
1759 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1760 Op->PSBHint.Val = Val;
1761 Op->PSBHint.Data = Str.data();
1762 Op->PSBHint.Length = Str.size();
1763 Op->StartLoc = S;
1764 Op->EndLoc = S;
1765 return Op;
1766 }
1767
David Blaikie960ea3f2014-06-08 16:18:35 +00001768 static std::unique_ptr<AArch64Operand>
1769 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1770 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1771 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001772 Op->ShiftExtend.Type = ShOp;
1773 Op->ShiftExtend.Amount = Val;
1774 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1775 Op->StartLoc = S;
1776 Op->EndLoc = E;
1777 return Op;
1778 }
1779};
1780
1781} // end anonymous namespace.
1782
1783void AArch64Operand::print(raw_ostream &OS) const {
1784 switch (Kind) {
1785 case k_FPImm:
1786 OS << "<fpimm " << getFPImm() << "("
1787 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1788 break;
1789 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001790 StringRef Name = getBarrierName();
1791 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001792 OS << "<barrier " << Name << ">";
1793 else
1794 OS << "<barrier invalid #" << getBarrier() << ">";
1795 break;
1796 }
1797 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001798 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001799 break;
1800 case k_ShiftedImm: {
1801 unsigned Shift = getShiftedImmShift();
1802 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001803 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001804 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1805 break;
1806 }
1807 case k_CondCode:
1808 OS << "<condcode " << getCondCode() << ">";
1809 break;
1810 case k_Register:
1811 OS << "<register " << getReg() << ">";
1812 break;
1813 case k_VectorList: {
1814 OS << "<vectorlist ";
1815 unsigned Reg = getVectorListStart();
1816 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1817 OS << Reg + i << " ";
1818 OS << ">";
1819 break;
1820 }
1821 case k_VectorIndex:
1822 OS << "<vectorindex " << getVectorIndex() << ">";
1823 break;
1824 case k_SysReg:
1825 OS << "<sysreg: " << getSysReg() << '>';
1826 break;
1827 case k_Token:
1828 OS << "'" << getToken() << "'";
1829 break;
1830 case k_SysCR:
1831 OS << "c" << getSysCR();
1832 break;
1833 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001834 StringRef Name = getPrefetchName();
1835 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001836 OS << "<prfop " << Name << ">";
1837 else
1838 OS << "<prfop invalid #" << getPrefetch() << ">";
1839 break;
1840 }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001841 case k_PSBHint: {
1842 OS << getPSBHintName();
1843 break;
1844 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001845 case k_ShiftExtend: {
1846 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1847 << getShiftExtendAmount();
1848 if (!hasShiftExtendAmount())
1849 OS << "<imp>";
1850 OS << '>';
1851 break;
1852 }
1853 }
1854}
1855
1856/// @name Auto-generated Match Functions
1857/// {
1858
1859static unsigned MatchRegisterName(StringRef Name);
1860
1861/// }
1862
1863static unsigned matchVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001864 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001865 .Case("v0", AArch64::Q0)
1866 .Case("v1", AArch64::Q1)
1867 .Case("v2", AArch64::Q2)
1868 .Case("v3", AArch64::Q3)
1869 .Case("v4", AArch64::Q4)
1870 .Case("v5", AArch64::Q5)
1871 .Case("v6", AArch64::Q6)
1872 .Case("v7", AArch64::Q7)
1873 .Case("v8", AArch64::Q8)
1874 .Case("v9", AArch64::Q9)
1875 .Case("v10", AArch64::Q10)
1876 .Case("v11", AArch64::Q11)
1877 .Case("v12", AArch64::Q12)
1878 .Case("v13", AArch64::Q13)
1879 .Case("v14", AArch64::Q14)
1880 .Case("v15", AArch64::Q15)
1881 .Case("v16", AArch64::Q16)
1882 .Case("v17", AArch64::Q17)
1883 .Case("v18", AArch64::Q18)
1884 .Case("v19", AArch64::Q19)
1885 .Case("v20", AArch64::Q20)
1886 .Case("v21", AArch64::Q21)
1887 .Case("v22", AArch64::Q22)
1888 .Case("v23", AArch64::Q23)
1889 .Case("v24", AArch64::Q24)
1890 .Case("v25", AArch64::Q25)
1891 .Case("v26", AArch64::Q26)
1892 .Case("v27", AArch64::Q27)
1893 .Case("v28", AArch64::Q28)
1894 .Case("v29", AArch64::Q29)
1895 .Case("v30", AArch64::Q30)
1896 .Case("v31", AArch64::Q31)
1897 .Default(0);
1898}
1899
1900static bool isValidVectorKind(StringRef Name) {
1901 return StringSwitch<bool>(Name.lower())
1902 .Case(".8b", true)
1903 .Case(".16b", true)
1904 .Case(".4h", true)
1905 .Case(".8h", true)
1906 .Case(".2s", true)
1907 .Case(".4s", true)
1908 .Case(".1d", true)
1909 .Case(".2d", true)
1910 .Case(".1q", true)
1911 // Accept the width neutral ones, too, for verbose syntax. If those
1912 // aren't used in the right places, the token operand won't match so
1913 // all will work out.
1914 .Case(".b", true)
1915 .Case(".h", true)
1916 .Case(".s", true)
1917 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001918 // Needed for fp16 scalar pairwise reductions
1919 .Case(".2h", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001920 .Default(false);
1921}
1922
1923static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1924 char &ElementKind) {
1925 assert(isValidVectorKind(Name));
1926
1927 ElementKind = Name.lower()[Name.size() - 1];
1928 NumElements = 0;
1929
1930 if (Name.size() == 2)
1931 return;
1932
1933 // Parse the lane count
1934 Name = Name.drop_front();
1935 while (isdigit(Name.front())) {
1936 NumElements = 10 * NumElements + (Name.front() - '0');
1937 Name = Name.drop_front();
1938 }
1939}
1940
1941bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1942 SMLoc &EndLoc) {
1943 StartLoc = getLoc();
1944 RegNo = tryParseRegister();
1945 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1946 return (RegNo == (unsigned)-1);
1947}
1948
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001949// Matches a register name or register alias previously defined by '.req'
1950unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
1951 bool isVector) {
1952 unsigned RegNum = isVector ? matchVectorRegName(Name)
1953 : MatchRegisterName(Name);
1954
1955 if (RegNum == 0) {
1956 // Check for aliases registered via .req. Canonicalize to lower case.
1957 // That's more consistent since register names are case insensitive, and
1958 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1959 auto Entry = RegisterReqs.find(Name.lower());
1960 if (Entry == RegisterReqs.end())
1961 return 0;
1962 // set RegNum if the match is the right kind of register
1963 if (isVector == Entry->getValue().first)
1964 RegNum = Entry->getValue().second;
1965 }
1966 return RegNum;
1967}
1968
Tim Northover3b0846e2014-05-24 12:50:23 +00001969/// tryParseRegister - Try to parse a register name. The token must be an
1970/// Identifier when called, and if it is a register name the token is eaten and
1971/// the register is added to the operand list.
1972int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001973 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001974 const AsmToken &Tok = Parser.getTok();
1975 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1976
1977 std::string lowerCase = Tok.getString().lower();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001978 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
Tim Northover3b0846e2014-05-24 12:50:23 +00001979 // Also handle a few aliases of registers.
1980 if (RegNum == 0)
1981 RegNum = StringSwitch<unsigned>(lowerCase)
1982 .Case("fp", AArch64::FP)
1983 .Case("lr", AArch64::LR)
1984 .Case("x31", AArch64::XZR)
1985 .Case("w31", AArch64::WZR)
1986 .Default(0);
1987
1988 if (RegNum == 0)
1989 return -1;
1990
1991 Parser.Lex(); // Eat identifier token.
1992 return RegNum;
1993}
1994
1995/// tryMatchVectorRegister - Try to parse a vector register name with optional
1996/// kind specifier. If it is a register specifier, eat the token and return it.
1997int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001998 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001999 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2000 TokError("vector register expected");
2001 return -1;
2002 }
2003
2004 StringRef Name = Parser.getTok().getString();
2005 // If there is a kind specifier, it's separated from the register name by
2006 // a '.'.
2007 size_t Start = 0, Next = Name.find('.');
2008 StringRef Head = Name.slice(Start, Next);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002009 unsigned RegNum = matchRegisterNameAlias(Head, true);
2010
Tim Northover3b0846e2014-05-24 12:50:23 +00002011 if (RegNum) {
2012 if (Next != StringRef::npos) {
2013 Kind = Name.slice(Next, StringRef::npos);
2014 if (!isValidVectorKind(Kind)) {
2015 TokError("invalid vector kind qualifier");
2016 return -1;
2017 }
2018 }
2019 Parser.Lex(); // Eat the register token.
2020 return RegNum;
2021 }
2022
2023 if (expected)
2024 TokError("vector register expected");
2025 return -1;
2026}
2027
2028/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002029OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002030AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002031 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002032 SMLoc S = getLoc();
2033
2034 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2035 Error(S, "Expected cN operand where 0 <= N <= 15");
2036 return MatchOperand_ParseFail;
2037 }
2038
2039 StringRef Tok = Parser.getTok().getIdentifier();
2040 if (Tok[0] != 'c' && Tok[0] != 'C') {
2041 Error(S, "Expected cN operand where 0 <= N <= 15");
2042 return MatchOperand_ParseFail;
2043 }
2044
2045 uint32_t CRNum;
2046 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2047 if (BadNum || CRNum > 15) {
2048 Error(S, "Expected cN operand where 0 <= N <= 15");
2049 return MatchOperand_ParseFail;
2050 }
2051
2052 Parser.Lex(); // Eat identifier token.
2053 Operands.push_back(
2054 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2055 return MatchOperand_Success;
2056}
2057
2058/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002059OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002060AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002061 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002062 SMLoc S = getLoc();
2063 const AsmToken &Tok = Parser.getTok();
2064 // Either an identifier for named values or a 5-bit immediate.
2065 bool Hash = Tok.is(AsmToken::Hash);
2066 if (Hash || Tok.is(AsmToken::Integer)) {
2067 if (Hash)
2068 Parser.Lex(); // Eat hash token.
2069 const MCExpr *ImmVal;
2070 if (getParser().parseExpression(ImmVal))
2071 return MatchOperand_ParseFail;
2072
2073 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2074 if (!MCE) {
2075 TokError("immediate value expected for prefetch operand");
2076 return MatchOperand_ParseFail;
2077 }
2078 unsigned prfop = MCE->getValue();
2079 if (prfop > 31) {
2080 TokError("prefetch operand out of range, [0,31] expected");
2081 return MatchOperand_ParseFail;
2082 }
2083
Tim Northovere6ae6762016-07-05 21:23:04 +00002084 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2085 Operands.push_back(AArch64Operand::CreatePrefetch(
2086 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002087 return MatchOperand_Success;
2088 }
2089
2090 if (Tok.isNot(AsmToken::Identifier)) {
2091 TokError("pre-fetch hint expected");
2092 return MatchOperand_ParseFail;
2093 }
2094
Tim Northovere6ae6762016-07-05 21:23:04 +00002095 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2096 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002097 TokError("pre-fetch hint expected");
2098 return MatchOperand_ParseFail;
2099 }
2100
2101 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002102 Operands.push_back(AArch64Operand::CreatePrefetch(
2103 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002104 return MatchOperand_Success;
2105}
2106
Oliver Stannarda34e4702015-12-01 10:48:51 +00002107/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002108OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002109AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2110 MCAsmParser &Parser = getParser();
2111 SMLoc S = getLoc();
2112 const AsmToken &Tok = Parser.getTok();
2113 if (Tok.isNot(AsmToken::Identifier)) {
2114 TokError("invalid operand for instruction");
2115 return MatchOperand_ParseFail;
2116 }
2117
Tim Northovere6ae6762016-07-05 21:23:04 +00002118 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2119 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002120 TokError("invalid operand for instruction");
2121 return MatchOperand_ParseFail;
2122 }
2123
2124 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002125 Operands.push_back(AArch64Operand::CreatePSBHint(
2126 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002127 return MatchOperand_Success;
2128}
2129
Tim Northover3b0846e2014-05-24 12:50:23 +00002130/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2131/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002132OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002133AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002134 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002135 SMLoc S = getLoc();
2136 const MCExpr *Expr;
2137
2138 if (Parser.getTok().is(AsmToken::Hash)) {
2139 Parser.Lex(); // Eat hash token.
2140 }
2141
2142 if (parseSymbolicImmVal(Expr))
2143 return MatchOperand_ParseFail;
2144
2145 AArch64MCExpr::VariantKind ELFRefKind;
2146 MCSymbolRefExpr::VariantKind DarwinRefKind;
2147 int64_t Addend;
2148 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2149 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2150 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2151 // No modifier was specified at all; this is the syntax for an ELF basic
2152 // ADRP relocation (unfortunately).
2153 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002154 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002155 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2156 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2157 Addend != 0) {
2158 Error(S, "gotpage label reference not allowed an addend");
2159 return MatchOperand_ParseFail;
2160 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2161 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2162 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2163 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2164 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2165 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2166 // The operand must be an @page or @gotpage qualified symbolref.
2167 Error(S, "page or gotpage label reference expected");
2168 return MatchOperand_ParseFail;
2169 }
2170 }
2171
2172 // We have either a label reference possibly with addend or an immediate. The
2173 // addend is a raw value here. The linker will adjust it to only reference the
2174 // page.
2175 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2176 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2177
2178 return MatchOperand_Success;
2179}
2180
2181/// tryParseAdrLabel - Parse and validate a source label for the ADR
2182/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002183OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002184AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002185 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002186 SMLoc S = getLoc();
2187 const MCExpr *Expr;
2188
2189 if (Parser.getTok().is(AsmToken::Hash)) {
2190 Parser.Lex(); // Eat hash token.
2191 }
2192
2193 if (getParser().parseExpression(Expr))
2194 return MatchOperand_ParseFail;
2195
2196 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2197 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2198
2199 return MatchOperand_Success;
2200}
2201
2202/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002203OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002204AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002205 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002206 SMLoc S = getLoc();
2207
2208 bool Hash = false;
2209 if (Parser.getTok().is(AsmToken::Hash)) {
2210 Parser.Lex(); // Eat '#'
2211 Hash = true;
2212 }
2213
2214 // Handle negation, as that still comes through as a separate token.
2215 bool isNegative = false;
2216 if (Parser.getTok().is(AsmToken::Minus)) {
2217 isNegative = true;
2218 Parser.Lex();
2219 }
2220 const AsmToken &Tok = Parser.getTok();
2221 if (Tok.is(AsmToken::Real)) {
2222 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002223 if (isNegative)
2224 RealVal.changeSign();
2225
Tim Northover3b0846e2014-05-24 12:50:23 +00002226 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002227 int Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2228 Parser.Lex(); // Eat the token.
2229 // Check for out of range values. As an exception, we let Zero through,
2230 // as we handle that special case in post-processing before matching in
2231 // order to use the zero register for it.
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002232 if (Val == -1 && !RealVal.isPosZero()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002233 TokError("expected compatible register or floating-point constant");
2234 return MatchOperand_ParseFail;
2235 }
2236 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2237 return MatchOperand_Success;
2238 }
2239 if (Tok.is(AsmToken::Integer)) {
2240 int64_t Val;
2241 if (!isNegative && Tok.getString().startswith("0x")) {
2242 Val = Tok.getIntVal();
2243 if (Val > 255 || Val < 0) {
2244 TokError("encoded floating point value out of range");
2245 return MatchOperand_ParseFail;
2246 }
2247 } else {
2248 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
2249 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2250 // If we had a '-' in front, toggle the sign bit.
2251 IntVal ^= (uint64_t)isNegative << 63;
2252 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2253 }
2254 Parser.Lex(); // Eat the token.
2255 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2256 return MatchOperand_Success;
2257 }
2258
2259 if (!Hash)
2260 return MatchOperand_NoMatch;
2261
2262 TokError("invalid floating point immediate");
2263 return MatchOperand_ParseFail;
2264}
2265
2266/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002267OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002268AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002269 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002270 SMLoc S = getLoc();
2271
2272 if (Parser.getTok().is(AsmToken::Hash))
2273 Parser.Lex(); // Eat '#'
2274 else if (Parser.getTok().isNot(AsmToken::Integer))
2275 // Operand should start from # or should be integer, emit error otherwise.
2276 return MatchOperand_NoMatch;
2277
2278 const MCExpr *Imm;
2279 if (parseSymbolicImmVal(Imm))
2280 return MatchOperand_ParseFail;
2281 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2282 uint64_t ShiftAmount = 0;
2283 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2284 if (MCE) {
2285 int64_t Val = MCE->getValue();
2286 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002287 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002288 ShiftAmount = 12;
2289 }
2290 }
2291 SMLoc E = Parser.getTok().getLoc();
2292 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2293 getContext()));
2294 return MatchOperand_Success;
2295 }
2296
2297 // Eat ','
2298 Parser.Lex();
2299
2300 // The optional operand must be "lsl #N" where N is non-negative.
2301 if (!Parser.getTok().is(AsmToken::Identifier) ||
2302 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2303 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2304 return MatchOperand_ParseFail;
2305 }
2306
2307 // Eat 'lsl'
2308 Parser.Lex();
2309
2310 if (Parser.getTok().is(AsmToken::Hash)) {
2311 Parser.Lex();
2312 }
2313
2314 if (Parser.getTok().isNot(AsmToken::Integer)) {
2315 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2316 return MatchOperand_ParseFail;
2317 }
2318
2319 int64_t ShiftAmount = Parser.getTok().getIntVal();
2320
2321 if (ShiftAmount < 0) {
2322 Error(Parser.getTok().getLoc(), "positive shift amount required");
2323 return MatchOperand_ParseFail;
2324 }
2325 Parser.Lex(); // Eat the number
2326
2327 SMLoc E = Parser.getTok().getLoc();
2328 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2329 S, E, getContext()));
2330 return MatchOperand_Success;
2331}
2332
2333/// parseCondCodeString - Parse a Condition Code string.
2334AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2335 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2336 .Case("eq", AArch64CC::EQ)
2337 .Case("ne", AArch64CC::NE)
2338 .Case("cs", AArch64CC::HS)
2339 .Case("hs", AArch64CC::HS)
2340 .Case("cc", AArch64CC::LO)
2341 .Case("lo", AArch64CC::LO)
2342 .Case("mi", AArch64CC::MI)
2343 .Case("pl", AArch64CC::PL)
2344 .Case("vs", AArch64CC::VS)
2345 .Case("vc", AArch64CC::VC)
2346 .Case("hi", AArch64CC::HI)
2347 .Case("ls", AArch64CC::LS)
2348 .Case("ge", AArch64CC::GE)
2349 .Case("lt", AArch64CC::LT)
2350 .Case("gt", AArch64CC::GT)
2351 .Case("le", AArch64CC::LE)
2352 .Case("al", AArch64CC::AL)
2353 .Case("nv", AArch64CC::NV)
2354 .Default(AArch64CC::Invalid);
2355 return CC;
2356}
2357
2358/// parseCondCode - Parse a Condition Code operand.
2359bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2360 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002361 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002362 SMLoc S = getLoc();
2363 const AsmToken &Tok = Parser.getTok();
2364 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2365
2366 StringRef Cond = Tok.getString();
2367 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2368 if (CC == AArch64CC::Invalid)
2369 return TokError("invalid condition code");
2370 Parser.Lex(); // Eat identifier token.
2371
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002372 if (invertCondCode) {
2373 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2374 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002375 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002376 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002377
2378 Operands.push_back(
2379 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2380 return false;
2381}
2382
2383/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2384/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002385OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002386AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002387 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002388 const AsmToken &Tok = Parser.getTok();
2389 std::string LowerID = Tok.getString().lower();
2390 AArch64_AM::ShiftExtendType ShOp =
2391 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2392 .Case("lsl", AArch64_AM::LSL)
2393 .Case("lsr", AArch64_AM::LSR)
2394 .Case("asr", AArch64_AM::ASR)
2395 .Case("ror", AArch64_AM::ROR)
2396 .Case("msl", AArch64_AM::MSL)
2397 .Case("uxtb", AArch64_AM::UXTB)
2398 .Case("uxth", AArch64_AM::UXTH)
2399 .Case("uxtw", AArch64_AM::UXTW)
2400 .Case("uxtx", AArch64_AM::UXTX)
2401 .Case("sxtb", AArch64_AM::SXTB)
2402 .Case("sxth", AArch64_AM::SXTH)
2403 .Case("sxtw", AArch64_AM::SXTW)
2404 .Case("sxtx", AArch64_AM::SXTX)
2405 .Default(AArch64_AM::InvalidShiftExtend);
2406
2407 if (ShOp == AArch64_AM::InvalidShiftExtend)
2408 return MatchOperand_NoMatch;
2409
2410 SMLoc S = Tok.getLoc();
2411 Parser.Lex();
2412
2413 bool Hash = getLexer().is(AsmToken::Hash);
2414 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2415 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2416 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2417 ShOp == AArch64_AM::MSL) {
2418 // We expect a number here.
2419 TokError("expected #imm after shift specifier");
2420 return MatchOperand_ParseFail;
2421 }
2422
2423 // "extend" type operatoins don't need an immediate, #0 is implicit.
2424 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2425 Operands.push_back(
2426 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2427 return MatchOperand_Success;
2428 }
2429
2430 if (Hash)
2431 Parser.Lex(); // Eat the '#'.
2432
Jim Grosbach57fd2622014-09-23 22:16:02 +00002433 // Make sure we do actually have a number or a parenthesized expression.
2434 SMLoc E = Parser.getTok().getLoc();
2435 if (!Parser.getTok().is(AsmToken::Integer) &&
2436 !Parser.getTok().is(AsmToken::LParen)) {
2437 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002438 return MatchOperand_ParseFail;
2439 }
2440
2441 const MCExpr *ImmVal;
2442 if (getParser().parseExpression(ImmVal))
2443 return MatchOperand_ParseFail;
2444
2445 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2446 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002447 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002448 return MatchOperand_ParseFail;
2449 }
2450
Jim Grosbach57fd2622014-09-23 22:16:02 +00002451 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002452 Operands.push_back(AArch64Operand::CreateShiftExtend(
2453 ShOp, MCE->getValue(), true, S, E, getContext()));
2454 return MatchOperand_Success;
2455}
2456
2457/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2458/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2459bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2460 OperandVector &Operands) {
2461 if (Name.find('.') != StringRef::npos)
2462 return TokError("invalid operand");
2463
2464 Mnemonic = Name;
2465 Operands.push_back(
2466 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2467
Rafael Espindola961d4692014-11-11 05:18:41 +00002468 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002469 const AsmToken &Tok = Parser.getTok();
2470 StringRef Op = Tok.getString();
2471 SMLoc S = Tok.getLoc();
2472
2473 const MCExpr *Expr = nullptr;
2474
2475#define SYS_ALIAS(op1, Cn, Cm, op2) \
2476 do { \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002477 Expr = MCConstantExpr::create(op1, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002478 Operands.push_back( \
2479 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2480 Operands.push_back( \
2481 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext())); \
2482 Operands.push_back( \
2483 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext())); \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002484 Expr = MCConstantExpr::create(op2, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002485 Operands.push_back( \
2486 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2487 } while (0)
2488
2489 if (Mnemonic == "ic") {
2490 if (!Op.compare_lower("ialluis")) {
2491 // SYS #0, C7, C1, #0
2492 SYS_ALIAS(0, 7, 1, 0);
2493 } else if (!Op.compare_lower("iallu")) {
2494 // SYS #0, C7, C5, #0
2495 SYS_ALIAS(0, 7, 5, 0);
2496 } else if (!Op.compare_lower("ivau")) {
2497 // SYS #3, C7, C5, #1
2498 SYS_ALIAS(3, 7, 5, 1);
2499 } else {
2500 return TokError("invalid operand for IC instruction");
2501 }
2502 } else if (Mnemonic == "dc") {
2503 if (!Op.compare_lower("zva")) {
2504 // SYS #3, C7, C4, #1
2505 SYS_ALIAS(3, 7, 4, 1);
2506 } else if (!Op.compare_lower("ivac")) {
2507 // SYS #3, C7, C6, #1
2508 SYS_ALIAS(0, 7, 6, 1);
2509 } else if (!Op.compare_lower("isw")) {
2510 // SYS #0, C7, C6, #2
2511 SYS_ALIAS(0, 7, 6, 2);
2512 } else if (!Op.compare_lower("cvac")) {
2513 // SYS #3, C7, C10, #1
2514 SYS_ALIAS(3, 7, 10, 1);
2515 } else if (!Op.compare_lower("csw")) {
2516 // SYS #0, C7, C10, #2
2517 SYS_ALIAS(0, 7, 10, 2);
2518 } else if (!Op.compare_lower("cvau")) {
2519 // SYS #3, C7, C11, #1
2520 SYS_ALIAS(3, 7, 11, 1);
2521 } else if (!Op.compare_lower("civac")) {
2522 // SYS #3, C7, C14, #1
2523 SYS_ALIAS(3, 7, 14, 1);
2524 } else if (!Op.compare_lower("cisw")) {
2525 // SYS #0, C7, C14, #2
2526 SYS_ALIAS(0, 7, 14, 2);
Oliver Stannard1a81cc9f2015-11-26 15:28:47 +00002527 } else if (!Op.compare_lower("cvap")) {
2528 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2529 // SYS #3, C7, C12, #1
2530 SYS_ALIAS(3, 7, 12, 1);
2531 } else {
2532 return TokError("DC CVAP requires ARMv8.2a");
2533 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002534 } else {
2535 return TokError("invalid operand for DC instruction");
2536 }
2537 } else if (Mnemonic == "at") {
2538 if (!Op.compare_lower("s1e1r")) {
2539 // SYS #0, C7, C8, #0
2540 SYS_ALIAS(0, 7, 8, 0);
2541 } else if (!Op.compare_lower("s1e2r")) {
2542 // SYS #4, C7, C8, #0
2543 SYS_ALIAS(4, 7, 8, 0);
2544 } else if (!Op.compare_lower("s1e3r")) {
2545 // SYS #6, C7, C8, #0
2546 SYS_ALIAS(6, 7, 8, 0);
2547 } else if (!Op.compare_lower("s1e1w")) {
2548 // SYS #0, C7, C8, #1
2549 SYS_ALIAS(0, 7, 8, 1);
2550 } else if (!Op.compare_lower("s1e2w")) {
2551 // SYS #4, C7, C8, #1
2552 SYS_ALIAS(4, 7, 8, 1);
2553 } else if (!Op.compare_lower("s1e3w")) {
2554 // SYS #6, C7, C8, #1
2555 SYS_ALIAS(6, 7, 8, 1);
2556 } else if (!Op.compare_lower("s1e0r")) {
2557 // SYS #0, C7, C8, #3
2558 SYS_ALIAS(0, 7, 8, 2);
2559 } else if (!Op.compare_lower("s1e0w")) {
2560 // SYS #0, C7, C8, #3
2561 SYS_ALIAS(0, 7, 8, 3);
2562 } else if (!Op.compare_lower("s12e1r")) {
2563 // SYS #4, C7, C8, #4
2564 SYS_ALIAS(4, 7, 8, 4);
2565 } else if (!Op.compare_lower("s12e1w")) {
2566 // SYS #4, C7, C8, #5
2567 SYS_ALIAS(4, 7, 8, 5);
2568 } else if (!Op.compare_lower("s12e0r")) {
2569 // SYS #4, C7, C8, #6
2570 SYS_ALIAS(4, 7, 8, 6);
2571 } else if (!Op.compare_lower("s12e0w")) {
2572 // SYS #4, C7, C8, #7
2573 SYS_ALIAS(4, 7, 8, 7);
Oliver Stannard64c167d2015-11-26 15:34:44 +00002574 } else if (!Op.compare_lower("s1e1rp")) {
2575 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2576 // SYS #0, C7, C9, #0
2577 SYS_ALIAS(0, 7, 9, 0);
2578 } else {
2579 return TokError("AT S1E1RP requires ARMv8.2a");
2580 }
2581 } else if (!Op.compare_lower("s1e1wp")) {
2582 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2583 // SYS #0, C7, C9, #1
2584 SYS_ALIAS(0, 7, 9, 1);
2585 } else {
2586 return TokError("AT S1E1WP requires ARMv8.2a");
2587 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002588 } else {
2589 return TokError("invalid operand for AT instruction");
2590 }
2591 } else if (Mnemonic == "tlbi") {
2592 if (!Op.compare_lower("vmalle1is")) {
2593 // SYS #0, C8, C3, #0
2594 SYS_ALIAS(0, 8, 3, 0);
2595 } else if (!Op.compare_lower("alle2is")) {
2596 // SYS #4, C8, C3, #0
2597 SYS_ALIAS(4, 8, 3, 0);
2598 } else if (!Op.compare_lower("alle3is")) {
2599 // SYS #6, C8, C3, #0
2600 SYS_ALIAS(6, 8, 3, 0);
2601 } else if (!Op.compare_lower("vae1is")) {
2602 // SYS #0, C8, C3, #1
2603 SYS_ALIAS(0, 8, 3, 1);
2604 } else if (!Op.compare_lower("vae2is")) {
2605 // SYS #4, C8, C3, #1
2606 SYS_ALIAS(4, 8, 3, 1);
2607 } else if (!Op.compare_lower("vae3is")) {
2608 // SYS #6, C8, C3, #1
2609 SYS_ALIAS(6, 8, 3, 1);
2610 } else if (!Op.compare_lower("aside1is")) {
2611 // SYS #0, C8, C3, #2
2612 SYS_ALIAS(0, 8, 3, 2);
2613 } else if (!Op.compare_lower("vaae1is")) {
2614 // SYS #0, C8, C3, #3
2615 SYS_ALIAS(0, 8, 3, 3);
2616 } else if (!Op.compare_lower("alle1is")) {
2617 // SYS #4, C8, C3, #4
2618 SYS_ALIAS(4, 8, 3, 4);
2619 } else if (!Op.compare_lower("vale1is")) {
2620 // SYS #0, C8, C3, #5
2621 SYS_ALIAS(0, 8, 3, 5);
2622 } else if (!Op.compare_lower("vaale1is")) {
2623 // SYS #0, C8, C3, #7
2624 SYS_ALIAS(0, 8, 3, 7);
2625 } else if (!Op.compare_lower("vmalle1")) {
2626 // SYS #0, C8, C7, #0
2627 SYS_ALIAS(0, 8, 7, 0);
2628 } else if (!Op.compare_lower("alle2")) {
2629 // SYS #4, C8, C7, #0
2630 SYS_ALIAS(4, 8, 7, 0);
2631 } else if (!Op.compare_lower("vale2is")) {
2632 // SYS #4, C8, C3, #5
2633 SYS_ALIAS(4, 8, 3, 5);
2634 } else if (!Op.compare_lower("vale3is")) {
2635 // SYS #6, C8, C3, #5
2636 SYS_ALIAS(6, 8, 3, 5);
2637 } else if (!Op.compare_lower("alle3")) {
2638 // SYS #6, C8, C7, #0
2639 SYS_ALIAS(6, 8, 7, 0);
2640 } else if (!Op.compare_lower("vae1")) {
2641 // SYS #0, C8, C7, #1
2642 SYS_ALIAS(0, 8, 7, 1);
2643 } else if (!Op.compare_lower("vae2")) {
2644 // SYS #4, C8, C7, #1
2645 SYS_ALIAS(4, 8, 7, 1);
2646 } else if (!Op.compare_lower("vae3")) {
2647 // SYS #6, C8, C7, #1
2648 SYS_ALIAS(6, 8, 7, 1);
2649 } else if (!Op.compare_lower("aside1")) {
2650 // SYS #0, C8, C7, #2
2651 SYS_ALIAS(0, 8, 7, 2);
2652 } else if (!Op.compare_lower("vaae1")) {
2653 // SYS #0, C8, C7, #3
2654 SYS_ALIAS(0, 8, 7, 3);
2655 } else if (!Op.compare_lower("alle1")) {
2656 // SYS #4, C8, C7, #4
2657 SYS_ALIAS(4, 8, 7, 4);
2658 } else if (!Op.compare_lower("vale1")) {
2659 // SYS #0, C8, C7, #5
2660 SYS_ALIAS(0, 8, 7, 5);
2661 } else if (!Op.compare_lower("vale2")) {
2662 // SYS #4, C8, C7, #5
2663 SYS_ALIAS(4, 8, 7, 5);
2664 } else if (!Op.compare_lower("vale3")) {
2665 // SYS #6, C8, C7, #5
2666 SYS_ALIAS(6, 8, 7, 5);
2667 } else if (!Op.compare_lower("vaale1")) {
2668 // SYS #0, C8, C7, #7
2669 SYS_ALIAS(0, 8, 7, 7);
2670 } else if (!Op.compare_lower("ipas2e1")) {
2671 // SYS #4, C8, C4, #1
2672 SYS_ALIAS(4, 8, 4, 1);
2673 } else if (!Op.compare_lower("ipas2le1")) {
2674 // SYS #4, C8, C4, #5
2675 SYS_ALIAS(4, 8, 4, 5);
2676 } else if (!Op.compare_lower("ipas2e1is")) {
2677 // SYS #4, C8, C4, #1
2678 SYS_ALIAS(4, 8, 0, 1);
2679 } else if (!Op.compare_lower("ipas2le1is")) {
2680 // SYS #4, C8, C4, #5
2681 SYS_ALIAS(4, 8, 0, 5);
2682 } else if (!Op.compare_lower("vmalls12e1")) {
2683 // SYS #4, C8, C7, #6
2684 SYS_ALIAS(4, 8, 7, 6);
2685 } else if (!Op.compare_lower("vmalls12e1is")) {
2686 // SYS #4, C8, C3, #6
2687 SYS_ALIAS(4, 8, 3, 6);
2688 } else {
2689 return TokError("invalid operand for TLBI instruction");
2690 }
2691 }
2692
2693#undef SYS_ALIAS
2694
2695 Parser.Lex(); // Eat operand.
2696
2697 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2698 bool HasRegister = false;
2699
2700 // Check for the optional register operand.
2701 if (getLexer().is(AsmToken::Comma)) {
2702 Parser.Lex(); // Eat comma.
2703
2704 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2705 return TokError("expected register operand");
2706
2707 HasRegister = true;
2708 }
2709
2710 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 return TokError("unexpected token in argument list");
2712 }
2713
2714 if (ExpectRegister && !HasRegister) {
2715 return TokError("specified " + Mnemonic + " op requires a register");
2716 }
2717 else if (!ExpectRegister && HasRegister) {
2718 return TokError("specified " + Mnemonic + " op does not use a register");
2719 }
2720
2721 Parser.Lex(); // Consume the EndOfStatement
2722 return false;
2723}
2724
Alex Bradbury58eba092016-11-01 16:32:05 +00002725OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002726AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002727 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002728 const AsmToken &Tok = Parser.getTok();
2729
2730 // Can be either a #imm style literal or an option name
2731 bool Hash = Tok.is(AsmToken::Hash);
2732 if (Hash || Tok.is(AsmToken::Integer)) {
2733 // Immediate operand.
2734 if (Hash)
2735 Parser.Lex(); // Eat the '#'
2736 const MCExpr *ImmVal;
2737 SMLoc ExprLoc = getLoc();
2738 if (getParser().parseExpression(ImmVal))
2739 return MatchOperand_ParseFail;
2740 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2741 if (!MCE) {
2742 Error(ExprLoc, "immediate value expected for barrier operand");
2743 return MatchOperand_ParseFail;
2744 }
2745 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2746 Error(ExprLoc, "barrier operand out of range");
2747 return MatchOperand_ParseFail;
2748 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002749 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2750 Operands.push_back(AArch64Operand::CreateBarrier(
2751 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002752 return MatchOperand_Success;
2753 }
2754
2755 if (Tok.isNot(AsmToken::Identifier)) {
2756 TokError("invalid operand for instruction");
2757 return MatchOperand_ParseFail;
2758 }
2759
Tim Northovere6ae6762016-07-05 21:23:04 +00002760 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2761 if (!DB) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002762 TokError("invalid barrier option name");
2763 return MatchOperand_ParseFail;
2764 }
2765
2766 // The only valid named option for ISB is 'sy'
Tim Northovere6ae6762016-07-05 21:23:04 +00002767 if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002768 TokError("'sy' or #imm operand expected");
2769 return MatchOperand_ParseFail;
2770 }
2771
Tim Northovere6ae6762016-07-05 21:23:04 +00002772 Operands.push_back(AArch64Operand::CreateBarrier(
2773 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002774 Parser.Lex(); // Consume the option
2775
2776 return MatchOperand_Success;
2777}
2778
Alex Bradbury58eba092016-11-01 16:32:05 +00002779OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002780AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002781 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002782 const AsmToken &Tok = Parser.getTok();
2783
2784 if (Tok.isNot(AsmToken::Identifier))
2785 return MatchOperand_NoMatch;
2786
Tim Northovere6ae6762016-07-05 21:23:04 +00002787 int MRSReg, MSRReg;
2788 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2789 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2790 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2791 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2792 } else
2793 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002794
Tim Northovere6ae6762016-07-05 21:23:04 +00002795 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2796 unsigned PStateImm = -1;
2797 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2798 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002799
Tim Northovere6ae6762016-07-05 21:23:04 +00002800 Operands.push_back(
2801 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2802 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002803 Parser.Lex(); // Eat identifier
2804
2805 return MatchOperand_Success;
2806}
2807
2808/// tryParseVectorRegister - Parse a vector register operand.
2809bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002810 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002811 if (Parser.getTok().isNot(AsmToken::Identifier))
2812 return true;
2813
2814 SMLoc S = getLoc();
2815 // Check for a vector register specifier first.
2816 StringRef Kind;
2817 int64_t Reg = tryMatchVectorRegister(Kind, false);
2818 if (Reg == -1)
2819 return true;
2820 Operands.push_back(
2821 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2822 // If there was an explicit qualifier, that goes on as a literal text
2823 // operand.
2824 if (!Kind.empty())
2825 Operands.push_back(
2826 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2827
2828 // If there is an index specifier following the register, parse that too.
2829 if (Parser.getTok().is(AsmToken::LBrac)) {
2830 SMLoc SIdx = getLoc();
2831 Parser.Lex(); // Eat left bracket token.
2832
2833 const MCExpr *ImmVal;
2834 if (getParser().parseExpression(ImmVal))
2835 return false;
2836 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2837 if (!MCE) {
2838 TokError("immediate value expected for vector index");
2839 return false;
2840 }
2841
2842 SMLoc E = getLoc();
2843 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2844 Error(E, "']' expected");
2845 return false;
2846 }
2847
2848 Parser.Lex(); // Eat right bracket token.
2849
2850 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2851 E, getContext()));
2852 }
2853
2854 return false;
2855}
2856
2857/// parseRegister - Parse a non-vector register operand.
2858bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002859 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002860 SMLoc S = getLoc();
2861 // Try for a vector register.
2862 if (!tryParseVectorRegister(Operands))
2863 return false;
2864
2865 // Try for a scalar register.
2866 int64_t Reg = tryParseRegister();
2867 if (Reg == -1)
2868 return true;
2869 Operands.push_back(
2870 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2871
2872 // A small number of instructions (FMOVXDhighr, for example) have "[1]"
2873 // as a string token in the instruction itself.
2874 if (getLexer().getKind() == AsmToken::LBrac) {
2875 SMLoc LBracS = getLoc();
2876 Parser.Lex();
2877 const AsmToken &Tok = Parser.getTok();
2878 if (Tok.is(AsmToken::Integer)) {
2879 SMLoc IntS = getLoc();
2880 int64_t Val = Tok.getIntVal();
2881 if (Val == 1) {
2882 Parser.Lex();
2883 if (getLexer().getKind() == AsmToken::RBrac) {
2884 SMLoc RBracS = getLoc();
2885 Parser.Lex();
2886 Operands.push_back(
2887 AArch64Operand::CreateToken("[", false, LBracS, getContext()));
2888 Operands.push_back(
2889 AArch64Operand::CreateToken("1", false, IntS, getContext()));
2890 Operands.push_back(
2891 AArch64Operand::CreateToken("]", false, RBracS, getContext()));
2892 return false;
2893 }
2894 }
2895 }
2896 }
2897
2898 return false;
2899}
2900
2901bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002902 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002903 bool HasELFModifier = false;
2904 AArch64MCExpr::VariantKind RefKind;
2905
2906 if (Parser.getTok().is(AsmToken::Colon)) {
2907 Parser.Lex(); // Eat ':"
2908 HasELFModifier = true;
2909
2910 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2911 Error(Parser.getTok().getLoc(),
2912 "expect relocation specifier in operand after ':'");
2913 return true;
2914 }
2915
2916 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2917 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2918 .Case("lo12", AArch64MCExpr::VK_LO12)
2919 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2920 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2921 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2922 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2923 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2924 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2925 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2926 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2927 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2928 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2929 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2930 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2931 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2932 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2933 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2934 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2935 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2936 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2937 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2938 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2939 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2940 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2941 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2942 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2943 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2944 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2945 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2946 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2947 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2948 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2949 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2950 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2951 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2952 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2953 .Default(AArch64MCExpr::VK_INVALID);
2954
2955 if (RefKind == AArch64MCExpr::VK_INVALID) {
2956 Error(Parser.getTok().getLoc(),
2957 "expect relocation specifier in operand after ':'");
2958 return true;
2959 }
2960
2961 Parser.Lex(); // Eat identifier
2962
2963 if (Parser.getTok().isNot(AsmToken::Colon)) {
2964 Error(Parser.getTok().getLoc(), "expect ':' after relocation specifier");
2965 return true;
2966 }
2967 Parser.Lex(); // Eat ':'
2968 }
2969
2970 if (getParser().parseExpression(ImmVal))
2971 return true;
2972
2973 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002974 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002975
2976 return false;
2977}
2978
2979/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2980bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002981 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002982 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2983 SMLoc S = getLoc();
2984 Parser.Lex(); // Eat left bracket token.
2985 StringRef Kind;
2986 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2987 if (FirstReg == -1)
2988 return true;
2989 int64_t PrevReg = FirstReg;
2990 unsigned Count = 1;
2991
2992 if (Parser.getTok().is(AsmToken::Minus)) {
2993 Parser.Lex(); // Eat the minus.
2994
2995 SMLoc Loc = getLoc();
2996 StringRef NextKind;
2997 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2998 if (Reg == -1)
2999 return true;
3000 // Any Kind suffices must match on all regs in the list.
3001 if (Kind != NextKind)
3002 return Error(Loc, "mismatched register size suffix");
3003
3004 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3005
3006 if (Space == 0 || Space > 3) {
3007 return Error(Loc, "invalid number of vectors");
3008 }
3009
3010 Count += Space;
3011 }
3012 else {
3013 while (Parser.getTok().is(AsmToken::Comma)) {
3014 Parser.Lex(); // Eat the comma token.
3015
3016 SMLoc Loc = getLoc();
3017 StringRef NextKind;
3018 int64_t Reg = tryMatchVectorRegister(NextKind, true);
3019 if (Reg == -1)
3020 return true;
3021 // Any Kind suffices must match on all regs in the list.
3022 if (Kind != NextKind)
3023 return Error(Loc, "mismatched register size suffix");
3024
3025 // Registers must be incremental (with wraparound at 31)
3026 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
3027 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
3028 return Error(Loc, "registers must be sequential");
3029
3030 PrevReg = Reg;
3031 ++Count;
3032 }
3033 }
3034
3035 if (Parser.getTok().isNot(AsmToken::RCurly))
3036 return Error(getLoc(), "'}' expected");
3037 Parser.Lex(); // Eat the '}' token.
3038
3039 if (Count > 4)
3040 return Error(S, "invalid number of vectors");
3041
3042 unsigned NumElements = 0;
3043 char ElementKind = 0;
3044 if (!Kind.empty())
3045 parseValidVectorKind(Kind, NumElements, ElementKind);
3046
3047 Operands.push_back(AArch64Operand::CreateVectorList(
3048 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
3049
3050 // If there is an index specifier following the list, parse that too.
3051 if (Parser.getTok().is(AsmToken::LBrac)) {
3052 SMLoc SIdx = getLoc();
3053 Parser.Lex(); // Eat left bracket token.
3054
3055 const MCExpr *ImmVal;
3056 if (getParser().parseExpression(ImmVal))
3057 return false;
3058 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3059 if (!MCE) {
3060 TokError("immediate value expected for vector index");
3061 return false;
3062 }
3063
3064 SMLoc E = getLoc();
3065 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3066 Error(E, "']' expected");
3067 return false;
3068 }
3069
3070 Parser.Lex(); // Eat right bracket token.
3071
3072 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3073 E, getContext()));
3074 }
3075 return false;
3076}
3077
Alex Bradbury58eba092016-11-01 16:32:05 +00003078OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003079AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003080 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003081 const AsmToken &Tok = Parser.getTok();
3082 if (!Tok.is(AsmToken::Identifier))
3083 return MatchOperand_NoMatch;
3084
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003085 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00003086
3087 MCContext &Ctx = getContext();
3088 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3089 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3090 return MatchOperand_NoMatch;
3091
3092 SMLoc S = getLoc();
3093 Parser.Lex(); // Eat register
3094
3095 if (Parser.getTok().isNot(AsmToken::Comma)) {
3096 Operands.push_back(
3097 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3098 return MatchOperand_Success;
3099 }
3100 Parser.Lex(); // Eat comma.
3101
3102 if (Parser.getTok().is(AsmToken::Hash))
3103 Parser.Lex(); // Eat hash
3104
3105 if (Parser.getTok().isNot(AsmToken::Integer)) {
3106 Error(getLoc(), "index must be absent or #0");
3107 return MatchOperand_ParseFail;
3108 }
3109
3110 const MCExpr *ImmVal;
3111 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3112 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3113 Error(getLoc(), "index must be absent or #0");
3114 return MatchOperand_ParseFail;
3115 }
3116
3117 Operands.push_back(
3118 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3119 return MatchOperand_Success;
3120}
3121
3122/// parseOperand - Parse a arm instruction operand. For now this parses the
3123/// operand regardless of the mnemonic.
3124bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3125 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003126 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003127 // Check if the current operand has a custom associated parser, if so, try to
3128 // custom parse the operand, or fallback to the general approach.
3129 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3130 if (ResTy == MatchOperand_Success)
3131 return false;
3132 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3133 // there was a match, but an error occurred, in which case, just return that
3134 // the operand parsing failed.
3135 if (ResTy == MatchOperand_ParseFail)
3136 return true;
3137
3138 // Nothing custom, so do general case parsing.
3139 SMLoc S, E;
3140 switch (getLexer().getKind()) {
3141 default: {
3142 SMLoc S = getLoc();
3143 const MCExpr *Expr;
3144 if (parseSymbolicImmVal(Expr))
3145 return Error(S, "invalid operand");
3146
3147 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3148 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3149 return false;
3150 }
3151 case AsmToken::LBrac: {
3152 SMLoc Loc = Parser.getTok().getLoc();
3153 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3154 getContext()));
3155 Parser.Lex(); // Eat '['
3156
3157 // There's no comma after a '[', so we can parse the next operand
3158 // immediately.
3159 return parseOperand(Operands, false, false);
3160 }
3161 case AsmToken::LCurly:
3162 return parseVectorList(Operands);
3163 case AsmToken::Identifier: {
3164 // If we're expecting a Condition Code operand, then just parse that.
3165 if (isCondCode)
3166 return parseCondCode(Operands, invertCondCode);
3167
3168 // If it's a register name, parse it.
3169 if (!parseRegister(Operands))
3170 return false;
3171
3172 // This could be an optional "shift" or "extend" operand.
3173 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3174 // We can only continue if no tokens were eaten.
3175 if (GotShift != MatchOperand_NoMatch)
3176 return GotShift;
3177
3178 // This was not a register so parse other operands that start with an
3179 // identifier (like labels) as expressions and create them as immediates.
3180 const MCExpr *IdVal;
3181 S = getLoc();
3182 if (getParser().parseExpression(IdVal))
3183 return true;
3184
3185 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3186 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3187 return false;
3188 }
3189 case AsmToken::Integer:
3190 case AsmToken::Real:
3191 case AsmToken::Hash: {
3192 // #42 -> immediate.
3193 S = getLoc();
3194 if (getLexer().is(AsmToken::Hash))
3195 Parser.Lex();
3196
3197 // Parse a negative sign
3198 bool isNegative = false;
3199 if (Parser.getTok().is(AsmToken::Minus)) {
3200 isNegative = true;
3201 // We need to consume this token only when we have a Real, otherwise
3202 // we let parseSymbolicImmVal take care of it
3203 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3204 Parser.Lex();
3205 }
3206
3207 // The only Real that should come through here is a literal #0.0 for
3208 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3209 // so convert the value.
3210 const AsmToken &Tok = Parser.getTok();
3211 if (Tok.is(AsmToken::Real)) {
3212 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3213 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3214 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3215 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3216 Mnemonic != "fcmlt")
3217 return TokError("unexpected floating point literal");
3218 else if (IntVal != 0 || isNegative)
3219 return TokError("expected floating-point constant #0.0");
3220 Parser.Lex(); // Eat the token.
3221
3222 Operands.push_back(
3223 AArch64Operand::CreateToken("#0", false, S, getContext()));
3224 Operands.push_back(
3225 AArch64Operand::CreateToken(".0", false, S, getContext()));
3226 return false;
3227 }
3228
3229 const MCExpr *ImmVal;
3230 if (parseSymbolicImmVal(ImmVal))
3231 return true;
3232
3233 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3234 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3235 return false;
3236 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003237 case AsmToken::Equal: {
3238 SMLoc Loc = Parser.getTok().getLoc();
3239 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
3240 return Error(Loc, "unexpected token in operand");
3241 Parser.Lex(); // Eat '='
3242 const MCExpr *SubExprVal;
3243 if (getParser().parseExpression(SubExprVal))
3244 return true;
3245
David Peixottoae5ba762014-07-18 16:05:14 +00003246 if (Operands.size() < 2 ||
3247 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003248 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003249
3250 bool IsXReg =
3251 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3252 Operands[1]->getReg());
3253
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003254 MCContext& Ctx = getContext();
3255 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3256 // 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 +00003257 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003258 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3259 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3260 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3261 ShiftAmt += 16;
3262 Imm >>= 16;
3263 }
3264 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3265 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3266 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003267 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003268 if (ShiftAmt)
3269 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3270 ShiftAmt, true, S, E, Ctx));
3271 return false;
3272 }
David Peixottoae5ba762014-07-18 16:05:14 +00003273 APInt Simm = APInt(64, Imm << ShiftAmt);
3274 // check if the immediate is an unsigned or signed 32-bit int for W regs
3275 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3276 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003277 }
3278 // 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 +00003279 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003280 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003281 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3282 return false;
3283 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003284 }
3285}
3286
3287/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3288/// operands.
3289bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3290 StringRef Name, SMLoc NameLoc,
3291 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003292 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003293 Name = StringSwitch<StringRef>(Name.lower())
3294 .Case("beq", "b.eq")
3295 .Case("bne", "b.ne")
3296 .Case("bhs", "b.hs")
3297 .Case("bcs", "b.cs")
3298 .Case("blo", "b.lo")
3299 .Case("bcc", "b.cc")
3300 .Case("bmi", "b.mi")
3301 .Case("bpl", "b.pl")
3302 .Case("bvs", "b.vs")
3303 .Case("bvc", "b.vc")
3304 .Case("bhi", "b.hi")
3305 .Case("bls", "b.ls")
3306 .Case("bge", "b.ge")
3307 .Case("blt", "b.lt")
3308 .Case("bgt", "b.gt")
3309 .Case("ble", "b.le")
3310 .Case("bal", "b.al")
3311 .Case("bnv", "b.nv")
3312 .Default(Name);
3313
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003314 // First check for the AArch64-specific .req directive.
3315 if (Parser.getTok().is(AsmToken::Identifier) &&
3316 Parser.getTok().getIdentifier() == ".req") {
3317 parseDirectiveReq(Name, NameLoc);
3318 // We always return 'error' for this, as we're done with this
3319 // statement and don't need to match the 'instruction."
3320 return true;
3321 }
3322
Tim Northover3b0846e2014-05-24 12:50:23 +00003323 // Create the leading tokens for the mnemonic, split by '.' characters.
3324 size_t Start = 0, Next = Name.find('.');
3325 StringRef Head = Name.slice(Start, Next);
3326
3327 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
3328 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi") {
3329 bool IsError = parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003330 return IsError;
3331 }
3332
3333 Operands.push_back(
3334 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3335 Mnemonic = Head;
3336
3337 // Handle condition codes for a branch mnemonic
3338 if (Head == "b" && Next != StringRef::npos) {
3339 Start = Next;
3340 Next = Name.find('.', Start + 1);
3341 Head = Name.slice(Start + 1, Next);
3342
3343 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3344 (Head.data() - Name.data()));
3345 AArch64CC::CondCode CC = parseCondCodeString(Head);
3346 if (CC == AArch64CC::Invalid)
3347 return Error(SuffixLoc, "invalid condition code");
3348 Operands.push_back(
3349 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3350 Operands.push_back(
3351 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3352 }
3353
3354 // Add the remaining tokens in the mnemonic.
3355 while (Next != StringRef::npos) {
3356 Start = Next;
3357 Next = Name.find('.', Start + 1);
3358 Head = Name.slice(Start, Next);
3359 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3360 (Head.data() - Name.data()) + 1);
3361 Operands.push_back(
3362 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3363 }
3364
3365 // Conditional compare instructions have a Condition Code operand, which needs
3366 // to be parsed and an immediate operand created.
3367 bool condCodeFourthOperand =
3368 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3369 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3370 Head == "csinc" || Head == "csinv" || Head == "csneg");
3371
3372 // These instructions are aliases to some of the conditional select
3373 // instructions. However, the condition code is inverted in the aliased
3374 // instruction.
3375 //
3376 // FIXME: Is this the correct way to handle these? Or should the parser
3377 // generate the aliased instructions directly?
3378 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3379 bool condCodeThirdOperand =
3380 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3381
3382 // Read the remaining operands.
3383 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3384 // Read the first operand.
3385 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003386 return true;
3387 }
3388
3389 unsigned N = 2;
3390 while (getLexer().is(AsmToken::Comma)) {
3391 Parser.Lex(); // Eat the comma.
3392
3393 // Parse and remember the operand.
3394 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3395 (N == 3 && condCodeThirdOperand) ||
3396 (N == 2 && condCodeSecondOperand),
3397 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003398 return true;
3399 }
3400
3401 // After successfully parsing some operands there are two special cases to
3402 // consider (i.e. notional operands not separated by commas). Both are due
3403 // to memory specifiers:
3404 // + An RBrac will end an address for load/store/prefetch
3405 // + An '!' will indicate a pre-indexed operation.
3406 //
3407 // It's someone else's responsibility to make sure these tokens are sane
3408 // in the given context!
3409 if (Parser.getTok().is(AsmToken::RBrac)) {
3410 SMLoc Loc = Parser.getTok().getLoc();
3411 Operands.push_back(AArch64Operand::CreateToken("]", false, Loc,
3412 getContext()));
3413 Parser.Lex();
3414 }
3415
3416 if (Parser.getTok().is(AsmToken::Exclaim)) {
3417 SMLoc Loc = Parser.getTok().getLoc();
3418 Operands.push_back(AArch64Operand::CreateToken("!", false, Loc,
3419 getContext()));
3420 Parser.Lex();
3421 }
3422
3423 ++N;
3424 }
3425 }
3426
3427 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3428 SMLoc Loc = Parser.getTok().getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003429 return Error(Loc, "unexpected token in argument list");
3430 }
3431
3432 Parser.Lex(); // Consume the EndOfStatement
3433 return false;
3434}
3435
3436// FIXME: This entire function is a giant hack to provide us with decent
3437// operand range validation/diagnostics until TableGen/MC can be extended
3438// to support autogeneration of this kind of validation.
3439bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3440 SmallVectorImpl<SMLoc> &Loc) {
3441 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3442 // Check for indexed addressing modes w/ the base register being the
3443 // same as a destination/source register or pair load where
3444 // the Rt == Rt2. All of those are undefined behaviour.
3445 switch (Inst.getOpcode()) {
3446 case AArch64::LDPSWpre:
3447 case AArch64::LDPWpost:
3448 case AArch64::LDPWpre:
3449 case AArch64::LDPXpost:
3450 case AArch64::LDPXpre: {
3451 unsigned Rt = Inst.getOperand(1).getReg();
3452 unsigned Rt2 = Inst.getOperand(2).getReg();
3453 unsigned Rn = Inst.getOperand(3).getReg();
3454 if (RI->isSubRegisterEq(Rn, Rt))
3455 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3456 "is also a destination");
3457 if (RI->isSubRegisterEq(Rn, Rt2))
3458 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3459 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003460 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003461 }
3462 case AArch64::LDPDi:
3463 case AArch64::LDPQi:
3464 case AArch64::LDPSi:
3465 case AArch64::LDPSWi:
3466 case AArch64::LDPWi:
3467 case AArch64::LDPXi: {
3468 unsigned Rt = Inst.getOperand(0).getReg();
3469 unsigned Rt2 = Inst.getOperand(1).getReg();
3470 if (Rt == Rt2)
3471 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3472 break;
3473 }
3474 case AArch64::LDPDpost:
3475 case AArch64::LDPDpre:
3476 case AArch64::LDPQpost:
3477 case AArch64::LDPQpre:
3478 case AArch64::LDPSpost:
3479 case AArch64::LDPSpre:
3480 case AArch64::LDPSWpost: {
3481 unsigned Rt = Inst.getOperand(1).getReg();
3482 unsigned Rt2 = Inst.getOperand(2).getReg();
3483 if (Rt == Rt2)
3484 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3485 break;
3486 }
3487 case AArch64::STPDpost:
3488 case AArch64::STPDpre:
3489 case AArch64::STPQpost:
3490 case AArch64::STPQpre:
3491 case AArch64::STPSpost:
3492 case AArch64::STPSpre:
3493 case AArch64::STPWpost:
3494 case AArch64::STPWpre:
3495 case AArch64::STPXpost:
3496 case AArch64::STPXpre: {
3497 unsigned Rt = Inst.getOperand(1).getReg();
3498 unsigned Rt2 = Inst.getOperand(2).getReg();
3499 unsigned Rn = Inst.getOperand(3).getReg();
3500 if (RI->isSubRegisterEq(Rn, Rt))
3501 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3502 "is also a source");
3503 if (RI->isSubRegisterEq(Rn, Rt2))
3504 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3505 "is also a source");
3506 break;
3507 }
3508 case AArch64::LDRBBpre:
3509 case AArch64::LDRBpre:
3510 case AArch64::LDRHHpre:
3511 case AArch64::LDRHpre:
3512 case AArch64::LDRSBWpre:
3513 case AArch64::LDRSBXpre:
3514 case AArch64::LDRSHWpre:
3515 case AArch64::LDRSHXpre:
3516 case AArch64::LDRSWpre:
3517 case AArch64::LDRWpre:
3518 case AArch64::LDRXpre:
3519 case AArch64::LDRBBpost:
3520 case AArch64::LDRBpost:
3521 case AArch64::LDRHHpost:
3522 case AArch64::LDRHpost:
3523 case AArch64::LDRSBWpost:
3524 case AArch64::LDRSBXpost:
3525 case AArch64::LDRSHWpost:
3526 case AArch64::LDRSHXpost:
3527 case AArch64::LDRSWpost:
3528 case AArch64::LDRWpost:
3529 case AArch64::LDRXpost: {
3530 unsigned Rt = Inst.getOperand(1).getReg();
3531 unsigned Rn = Inst.getOperand(2).getReg();
3532 if (RI->isSubRegisterEq(Rn, Rt))
3533 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3534 "is also a source");
3535 break;
3536 }
3537 case AArch64::STRBBpost:
3538 case AArch64::STRBpost:
3539 case AArch64::STRHHpost:
3540 case AArch64::STRHpost:
3541 case AArch64::STRWpost:
3542 case AArch64::STRXpost:
3543 case AArch64::STRBBpre:
3544 case AArch64::STRBpre:
3545 case AArch64::STRHHpre:
3546 case AArch64::STRHpre:
3547 case AArch64::STRWpre:
3548 case AArch64::STRXpre: {
3549 unsigned Rt = Inst.getOperand(1).getReg();
3550 unsigned Rn = Inst.getOperand(2).getReg();
3551 if (RI->isSubRegisterEq(Rn, Rt))
3552 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3553 "is also a source");
3554 break;
3555 }
3556 }
3557
3558 // Now check immediate ranges. Separate from the above as there is overlap
3559 // in the instructions being checked and this keeps the nested conditionals
3560 // to a minimum.
3561 switch (Inst.getOpcode()) {
3562 case AArch64::ADDSWri:
3563 case AArch64::ADDSXri:
3564 case AArch64::ADDWri:
3565 case AArch64::ADDXri:
3566 case AArch64::SUBSWri:
3567 case AArch64::SUBSXri:
3568 case AArch64::SUBWri:
3569 case AArch64::SUBXri: {
3570 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3571 // some slight duplication here.
3572 if (Inst.getOperand(2).isExpr()) {
3573 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3574 AArch64MCExpr::VariantKind ELFRefKind;
3575 MCSymbolRefExpr::VariantKind DarwinRefKind;
3576 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003577 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3578
3579 // Only allow these with ADDXri.
3580 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3581 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3582 Inst.getOpcode() == AArch64::ADDXri)
3583 return false;
3584
3585 // Only allow these with ADDXri/ADDWri
3586 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3587 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3588 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3589 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3590 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3591 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3592 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3593 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3594 (Inst.getOpcode() == AArch64::ADDXri ||
3595 Inst.getOpcode() == AArch64::ADDWri))
3596 return false;
3597
3598 // Don't allow symbol refs in the immediate field otherwise
3599 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3600 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3601 // 'cmp w0, 'borked')
3602 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003603 }
Diana Picusc93518d2016-10-11 09:17:47 +00003604 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003605 }
3606 return false;
3607 }
3608 default:
3609 return false;
3610 }
3611}
3612
3613bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3614 switch (ErrCode) {
3615 case Match_MissingFeature:
3616 return Error(Loc,
3617 "instruction requires a CPU feature not currently enabled");
3618 case Match_InvalidOperand:
3619 return Error(Loc, "invalid operand for instruction");
3620 case Match_InvalidSuffix:
3621 return Error(Loc, "invalid type suffix for instruction");
3622 case Match_InvalidCondCode:
3623 return Error(Loc, "expected AArch64 condition code");
3624 case Match_AddSubRegExtendSmall:
3625 return Error(Loc,
3626 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3627 case Match_AddSubRegExtendLarge:
3628 return Error(Loc,
3629 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3630 case Match_AddSubSecondSource:
3631 return Error(Loc,
3632 "expected compatible register, symbol or integer in range [0, 4095]");
3633 case Match_LogicalSecondSource:
3634 return Error(Loc, "expected compatible register or logical immediate");
3635 case Match_InvalidMovImm32Shift:
3636 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3637 case Match_InvalidMovImm64Shift:
3638 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3639 case Match_AddSubRegShift32:
3640 return Error(Loc,
3641 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3642 case Match_AddSubRegShift64:
3643 return Error(Loc,
3644 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3645 case Match_InvalidFPImm:
3646 return Error(Loc,
3647 "expected compatible register or floating-point constant");
3648 case Match_InvalidMemoryIndexedSImm9:
3649 return Error(Loc, "index must be an integer in range [-256, 255].");
3650 case Match_InvalidMemoryIndexed4SImm7:
3651 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3652 case Match_InvalidMemoryIndexed8SImm7:
3653 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3654 case Match_InvalidMemoryIndexed16SImm7:
3655 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3656 case Match_InvalidMemoryWExtend8:
3657 return Error(Loc,
3658 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3659 case Match_InvalidMemoryWExtend16:
3660 return Error(Loc,
3661 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3662 case Match_InvalidMemoryWExtend32:
3663 return Error(Loc,
3664 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3665 case Match_InvalidMemoryWExtend64:
3666 return Error(Loc,
3667 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3668 case Match_InvalidMemoryWExtend128:
3669 return Error(Loc,
3670 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3671 case Match_InvalidMemoryXExtend8:
3672 return Error(Loc,
3673 "expected 'lsl' or 'sxtx' with optional shift of #0");
3674 case Match_InvalidMemoryXExtend16:
3675 return Error(Loc,
3676 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3677 case Match_InvalidMemoryXExtend32:
3678 return Error(Loc,
3679 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3680 case Match_InvalidMemoryXExtend64:
3681 return Error(Loc,
3682 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3683 case Match_InvalidMemoryXExtend128:
3684 return Error(Loc,
3685 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3686 case Match_InvalidMemoryIndexed1:
3687 return Error(Loc, "index must be an integer in range [0, 4095].");
3688 case Match_InvalidMemoryIndexed2:
3689 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3690 case Match_InvalidMemoryIndexed4:
3691 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3692 case Match_InvalidMemoryIndexed8:
3693 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3694 case Match_InvalidMemoryIndexed16:
3695 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003696 case Match_InvalidImm0_1:
3697 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003698 case Match_InvalidImm0_7:
3699 return Error(Loc, "immediate must be an integer in range [0, 7].");
3700 case Match_InvalidImm0_15:
3701 return Error(Loc, "immediate must be an integer in range [0, 15].");
3702 case Match_InvalidImm0_31:
3703 return Error(Loc, "immediate must be an integer in range [0, 31].");
3704 case Match_InvalidImm0_63:
3705 return Error(Loc, "immediate must be an integer in range [0, 63].");
3706 case Match_InvalidImm0_127:
3707 return Error(Loc, "immediate must be an integer in range [0, 127].");
3708 case Match_InvalidImm0_65535:
3709 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3710 case Match_InvalidImm1_8:
3711 return Error(Loc, "immediate must be an integer in range [1, 8].");
3712 case Match_InvalidImm1_16:
3713 return Error(Loc, "immediate must be an integer in range [1, 16].");
3714 case Match_InvalidImm1_32:
3715 return Error(Loc, "immediate must be an integer in range [1, 32].");
3716 case Match_InvalidImm1_64:
3717 return Error(Loc, "immediate must be an integer in range [1, 64].");
3718 case Match_InvalidIndex1:
3719 return Error(Loc, "expected lane specifier '[1]'");
3720 case Match_InvalidIndexB:
3721 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3722 case Match_InvalidIndexH:
3723 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3724 case Match_InvalidIndexS:
3725 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3726 case Match_InvalidIndexD:
3727 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3728 case Match_InvalidLabel:
3729 return Error(Loc, "expected label or encodable integer pc offset");
3730 case Match_MRS:
3731 return Error(Loc, "expected readable system register");
3732 case Match_MSR:
3733 return Error(Loc, "expected writable system register or pstate");
3734 case Match_MnemonicFail:
3735 return Error(Loc, "unrecognized instruction mnemonic");
3736 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003737 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003738 }
3739}
3740
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003741static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003742
3743bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3744 OperandVector &Operands,
3745 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003746 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003747 bool MatchingInlineAsm) {
3748 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003749 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3750 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003751
David Blaikie960ea3f2014-06-08 16:18:35 +00003752 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003753 unsigned NumOperands = Operands.size();
3754
3755 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003756 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3757 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3758 if (Op2.isReg() && Op3.isImm()) {
3759 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003760 if (Op3CE) {
3761 uint64_t Op3Val = Op3CE->getValue();
3762 uint64_t NewOp3Val = 0;
3763 uint64_t NewOp4Val = 0;
3764 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003765 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003766 NewOp3Val = (32 - Op3Val) & 0x1f;
3767 NewOp4Val = 31 - Op3Val;
3768 } else {
3769 NewOp3Val = (64 - Op3Val) & 0x3f;
3770 NewOp4Val = 63 - Op3Val;
3771 }
3772
Jim Grosbach13760bd2015-05-30 01:25:56 +00003773 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3774 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003775
3776 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003777 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003778 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003779 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3780 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3781 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003782 }
3783 }
Tim Northover03b99f62015-04-30 18:28:58 +00003784 } else if (NumOperands == 4 && Tok == "bfc") {
3785 // FIXME: Horrible hack to handle BFC->BFM alias.
3786 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3787 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3788 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3789
3790 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3791 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3792 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3793
3794 if (LSBCE && WidthCE) {
3795 uint64_t LSB = LSBCE->getValue();
3796 uint64_t Width = WidthCE->getValue();
3797
3798 uint64_t RegWidth = 0;
3799 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3800 Op1.getReg()))
3801 RegWidth = 64;
3802 else
3803 RegWidth = 32;
3804
3805 if (LSB >= RegWidth)
3806 return Error(LSBOp.getStartLoc(),
3807 "expected integer in range [0, 31]");
3808 if (Width < 1 || Width > RegWidth)
3809 return Error(WidthOp.getStartLoc(),
3810 "expected integer in range [1, 32]");
3811
3812 uint64_t ImmR = 0;
3813 if (RegWidth == 32)
3814 ImmR = (32 - LSB) & 0x1f;
3815 else
3816 ImmR = (64 - LSB) & 0x3f;
3817
3818 uint64_t ImmS = Width - 1;
3819
3820 if (ImmR != 0 && ImmS >= ImmR)
3821 return Error(WidthOp.getStartLoc(),
3822 "requested insert overflows register");
3823
Jim Grosbach13760bd2015-05-30 01:25:56 +00003824 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3825 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003826 Operands[0] = AArch64Operand::CreateToken(
3827 "bfm", false, Op.getStartLoc(), getContext());
3828 Operands[2] = AArch64Operand::CreateReg(
3829 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3830 SMLoc(), getContext());
3831 Operands[3] = AArch64Operand::CreateImm(
3832 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3833 Operands.emplace_back(
3834 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3835 WidthOp.getEndLoc(), getContext()));
3836 }
3837 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003838 } else if (NumOperands == 5) {
3839 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3840 // UBFIZ -> UBFM aliases.
3841 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003842 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3843 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3844 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003845
David Blaikie960ea3f2014-06-08 16:18:35 +00003846 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3847 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3848 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003849
3850 if (Op3CE && Op4CE) {
3851 uint64_t Op3Val = Op3CE->getValue();
3852 uint64_t Op4Val = Op4CE->getValue();
3853
3854 uint64_t RegWidth = 0;
3855 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003856 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003857 RegWidth = 64;
3858 else
3859 RegWidth = 32;
3860
3861 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003862 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003863 "expected integer in range [0, 31]");
3864 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003865 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 "expected integer in range [1, 32]");
3867
3868 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003869 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003870 NewOp3Val = (32 - Op3Val) & 0x1f;
3871 else
3872 NewOp3Val = (64 - Op3Val) & 0x3f;
3873
3874 uint64_t NewOp4Val = Op4Val - 1;
3875
3876 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003877 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003878 "requested insert overflows register");
3879
3880 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003881 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003882 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003883 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003884 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003885 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003886 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003887 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003888 if (Tok == "bfi")
3889 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003890 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003891 else if (Tok == "sbfiz")
3892 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003893 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003894 else if (Tok == "ubfiz")
3895 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003896 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003897 else
3898 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003899 }
3900 }
3901
3902 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3903 // UBFX -> UBFM aliases.
3904 } else if (NumOperands == 5 &&
3905 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003906 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3907 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3908 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003909
David Blaikie960ea3f2014-06-08 16:18:35 +00003910 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3911 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3912 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003913
3914 if (Op3CE && Op4CE) {
3915 uint64_t Op3Val = Op3CE->getValue();
3916 uint64_t Op4Val = Op4CE->getValue();
3917
3918 uint64_t RegWidth = 0;
3919 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003920 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003921 RegWidth = 64;
3922 else
3923 RegWidth = 32;
3924
3925 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003926 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003927 "expected integer in range [0, 31]");
3928 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003929 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003930 "expected integer in range [1, 32]");
3931
3932 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3933
3934 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003935 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 "requested extract overflows register");
3937
3938 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003939 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003940 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003941 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003942 if (Tok == "bfxil")
3943 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003944 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003945 else if (Tok == "sbfx")
3946 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003947 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003948 else if (Tok == "ubfx")
3949 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003950 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003951 else
3952 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003953 }
3954 }
3955 }
3956 }
3957 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3958 // InstAlias can't quite handle this since the reg classes aren't
3959 // subclasses.
3960 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3961 // The source register can be Wn here, but the matcher expects a
3962 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003963 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3964 if (Op.isReg()) {
3965 unsigned Reg = getXRegFromWReg(Op.getReg());
3966 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3967 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003968 }
3969 }
3970 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3971 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003972 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3973 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003974 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003975 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003976 // The source register can be Wn here, but the matcher expects a
3977 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003978 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3979 if (Op.isReg()) {
3980 unsigned Reg = getXRegFromWReg(Op.getReg());
3981 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3982 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003983 }
3984 }
3985 }
3986 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3987 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003988 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3989 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003990 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003991 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003992 // The source register can be Wn here, but the matcher expects a
3993 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003994 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3995 if (Op.isReg()) {
3996 unsigned Reg = getWRegFromXReg(Op.getReg());
3997 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3998 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003999 }
4000 }
4001 }
4002
4003 // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
4004 if (NumOperands == 3 && Tok == "fmov") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004005 AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
4006 AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
4007 if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004008 unsigned zreg =
Oliver Stannardb25914e2015-11-27 13:04:48 +00004009 !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004010 RegOp.getReg())
Tim Northover3b0846e2014-05-24 12:50:23 +00004011 ? AArch64::WZR
4012 : AArch64::XZR;
David Blaikie960ea3f2014-06-08 16:18:35 +00004013 Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
4014 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004015 }
4016 }
4017
4018 MCInst Inst;
4019 // First try to match against the secondary set of tables containing the
4020 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4021 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004022 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004023
4024 // If that fails, try against the alternate table containing long-form NEON:
4025 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004026 if (MatchResult != Match_Success) {
4027 // But first, save the short-form match result: we can use it in case the
4028 // long-form match also fails.
4029 auto ShortFormNEONErrorInfo = ErrorInfo;
4030 auto ShortFormNEONMatchResult = MatchResult;
4031
Tim Northover3b0846e2014-05-24 12:50:23 +00004032 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004033 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004034
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004035 // Now, both matches failed, and the long-form match failed on the mnemonic
4036 // suffix token operand. The short-form match failure is probably more
4037 // relevant: use it instead.
4038 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004039 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004040 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4041 MatchResult = ShortFormNEONMatchResult;
4042 ErrorInfo = ShortFormNEONErrorInfo;
4043 }
4044 }
4045
4046
Tim Northover3b0846e2014-05-24 12:50:23 +00004047 switch (MatchResult) {
4048 case Match_Success: {
4049 // Perform range checking and other semantic validations
4050 SmallVector<SMLoc, 8> OperandLocs;
4051 NumOperands = Operands.size();
4052 for (unsigned i = 1; i < NumOperands; ++i)
4053 OperandLocs.push_back(Operands[i]->getStartLoc());
4054 if (validateInstruction(Inst, OperandLocs))
4055 return true;
4056
4057 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004058 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004059 return false;
4060 }
4061 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004062 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004063 // Special case the error message for the very common case where only
4064 // a single subtarget feature is missing (neon, e.g.).
4065 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004066 uint64_t Mask = 1;
4067 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4068 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004069 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004070 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004071 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004072 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004073 }
4074 return Error(IDLoc, Msg);
4075 }
4076 case Match_MnemonicFail:
4077 return showMatchError(IDLoc, MatchResult);
4078 case Match_InvalidOperand: {
4079 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004080
Tim Northover26bb14e2014-08-18 11:49:42 +00004081 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004082 if (ErrorInfo >= Operands.size())
4083 return Error(IDLoc, "too few operands for instruction");
4084
David Blaikie960ea3f2014-06-08 16:18:35 +00004085 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004086 if (ErrorLoc == SMLoc())
4087 ErrorLoc = IDLoc;
4088 }
4089 // If the match failed on a suffix token operand, tweak the diagnostic
4090 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004091 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4092 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004093 MatchResult = Match_InvalidSuffix;
4094
4095 return showMatchError(ErrorLoc, MatchResult);
4096 }
4097 case Match_InvalidMemoryIndexed1:
4098 case Match_InvalidMemoryIndexed2:
4099 case Match_InvalidMemoryIndexed4:
4100 case Match_InvalidMemoryIndexed8:
4101 case Match_InvalidMemoryIndexed16:
4102 case Match_InvalidCondCode:
4103 case Match_AddSubRegExtendSmall:
4104 case Match_AddSubRegExtendLarge:
4105 case Match_AddSubSecondSource:
4106 case Match_LogicalSecondSource:
4107 case Match_AddSubRegShift32:
4108 case Match_AddSubRegShift64:
4109 case Match_InvalidMovImm32Shift:
4110 case Match_InvalidMovImm64Shift:
4111 case Match_InvalidFPImm:
4112 case Match_InvalidMemoryWExtend8:
4113 case Match_InvalidMemoryWExtend16:
4114 case Match_InvalidMemoryWExtend32:
4115 case Match_InvalidMemoryWExtend64:
4116 case Match_InvalidMemoryWExtend128:
4117 case Match_InvalidMemoryXExtend8:
4118 case Match_InvalidMemoryXExtend16:
4119 case Match_InvalidMemoryXExtend32:
4120 case Match_InvalidMemoryXExtend64:
4121 case Match_InvalidMemoryXExtend128:
4122 case Match_InvalidMemoryIndexed4SImm7:
4123 case Match_InvalidMemoryIndexed8SImm7:
4124 case Match_InvalidMemoryIndexed16SImm7:
4125 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004126 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004127 case Match_InvalidImm0_7:
4128 case Match_InvalidImm0_15:
4129 case Match_InvalidImm0_31:
4130 case Match_InvalidImm0_63:
4131 case Match_InvalidImm0_127:
4132 case Match_InvalidImm0_65535:
4133 case Match_InvalidImm1_8:
4134 case Match_InvalidImm1_16:
4135 case Match_InvalidImm1_32:
4136 case Match_InvalidImm1_64:
4137 case Match_InvalidIndex1:
4138 case Match_InvalidIndexB:
4139 case Match_InvalidIndexH:
4140 case Match_InvalidIndexS:
4141 case Match_InvalidIndexD:
4142 case Match_InvalidLabel:
4143 case Match_MSR:
4144 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004145 if (ErrorInfo >= Operands.size())
4146 return Error(IDLoc, "too few operands for instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00004147 // Any time we get here, there's nothing fancy to do. Just get the
4148 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004149 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004150 if (ErrorLoc == SMLoc())
4151 ErrorLoc = IDLoc;
4152 return showMatchError(ErrorLoc, MatchResult);
4153 }
4154 }
4155
4156 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004157}
4158
4159/// ParseDirective parses the arm specific directives
4160bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004161 const MCObjectFileInfo::Environment Format =
4162 getContext().getObjectFileInfo()->getObjectFileType();
4163 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4164 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004165
Tim Northover3b0846e2014-05-24 12:50:23 +00004166 StringRef IDVal = DirectiveID.getIdentifier();
4167 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004168 if (IDVal == ".arch")
4169 return parseDirectiveArch(Loc);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004170 if (IDVal == ".cpu")
4171 return parseDirectiveCPU(Loc);
Tim Northover3b0846e2014-05-24 12:50:23 +00004172 if (IDVal == ".hword")
4173 return parseDirectiveWord(2, Loc);
4174 if (IDVal == ".word")
4175 return parseDirectiveWord(4, Loc);
4176 if (IDVal == ".xword")
4177 return parseDirectiveWord(8, Loc);
4178 if (IDVal == ".tlsdesccall")
4179 return parseDirectiveTLSDescCall(Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004180 if (IDVal == ".ltorg" || IDVal == ".pool")
4181 return parseDirectiveLtorg(Loc);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004182 if (IDVal == ".unreq")
Chad Rosieradc06312015-05-28 18:18:21 +00004183 return parseDirectiveUnreq(Loc);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004184
Chad Rosierdcd2a302014-10-22 20:35:57 +00004185 if (!IsMachO && !IsCOFF) {
4186 if (IDVal == ".inst")
4187 return parseDirectiveInst(Loc);
4188 }
Nirav Dave2364748a2016-09-16 18:30:20 +00004189 if (IDVal == MCLOHDirectiveName())
4190 return parseDirectiveLOH(IDVal, Loc);
Chad Rosierdcd2a302014-10-22 20:35:57 +00004191
Nirav Dave2364748a2016-09-16 18:30:20 +00004192 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004193}
4194
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004195static const struct {
4196 const char *Name;
4197 const FeatureBitset Features;
4198} ExtensionMap[] = {
4199 { "crc", {AArch64::FeatureCRC} },
4200 { "crypto", {AArch64::FeatureCrypto} },
4201 { "fp", {AArch64::FeatureFPARMv8} },
4202 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004203 { "ras", {AArch64::FeatureRAS} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004204
4205 // FIXME: Unsupported extensions
4206 { "lse", {} },
4207 { "pan", {} },
4208 { "lor", {} },
4209 { "rdma", {} },
4210 { "profile", {} },
4211};
4212
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004213/// parseDirectiveArch
4214/// ::= .arch token
4215bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4216 SMLoc ArchLoc = getLoc();
4217
4218 StringRef Arch, ExtensionString;
4219 std::tie(Arch, ExtensionString) =
4220 getParser().parseStringToEndOfStatement().trim().split('+');
4221
4222 unsigned ID = AArch64::parseArch(Arch);
Zijiao Mae56a53a2016-07-28 06:11:18 +00004223 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID)) {
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004224 Error(ArchLoc, "unknown arch name");
4225 return false;
4226 }
4227
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004228 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004229 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004230 AArch64::getArchFeatures(ID, AArch64Features);
4231 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4232 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004233
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004234 MCSubtargetInfo &STI = copySTI();
4235 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4236 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4237
4238 SmallVector<StringRef, 4> RequestedExtensions;
4239 if (!ExtensionString.empty())
4240 ExtensionString.split(RequestedExtensions, '+');
4241
4242 FeatureBitset Features = STI.getFeatureBits();
4243 for (auto Name : RequestedExtensions) {
4244 bool EnableFeature = true;
4245
4246 if (Name.startswith_lower("no")) {
4247 EnableFeature = false;
4248 Name = Name.substr(2);
4249 }
4250
4251 for (const auto &Extension : ExtensionMap) {
4252 if (Extension.Name != Name)
4253 continue;
4254
4255 if (Extension.Features.none())
4256 report_fatal_error("unsupported architectural extension: " + Name);
4257
4258 FeatureBitset ToggleFeatures = EnableFeature
4259 ? (~Features & Extension.Features)
4260 : ( Features & Extension.Features);
4261 uint64_t Features =
4262 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4263 setAvailableFeatures(Features);
4264 break;
4265 }
4266 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004267 return false;
4268}
4269
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004270/// parseDirectiveCPU
4271/// ::= .cpu id
4272bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
4273 SMLoc CPULoc = getLoc();
4274
4275 StringRef CPU, ExtensionString;
4276 std::tie(CPU, ExtensionString) =
4277 getParser().parseStringToEndOfStatement().trim().split('+');
4278
4279 SmallVector<StringRef, 4> RequestedExtensions;
4280 if (!ExtensionString.empty())
4281 ExtensionString.split(RequestedExtensions, '+');
4282
4283 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4284 // once that is tablegen'ed
4285 if (!getSTI().isCPUStringValid(CPU)) {
4286 Error(CPULoc, "unknown CPU name");
4287 return false;
4288 }
4289
4290 MCSubtargetInfo &STI = copySTI();
4291 STI.setDefaultFeatures(CPU, "");
4292
4293 FeatureBitset Features = STI.getFeatureBits();
4294 for (auto Name : RequestedExtensions) {
4295 bool EnableFeature = true;
4296
4297 if (Name.startswith_lower("no")) {
4298 EnableFeature = false;
4299 Name = Name.substr(2);
4300 }
4301
4302 for (const auto &Extension : ExtensionMap) {
4303 if (Extension.Name != Name)
4304 continue;
4305
4306 if (Extension.Features.none())
4307 report_fatal_error("unsupported architectural extension: " + Name);
4308
4309 FeatureBitset ToggleFeatures = EnableFeature
4310 ? (~Features & Extension.Features)
4311 : ( Features & Extension.Features);
4312 uint64_t Features =
4313 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4314 setAvailableFeatures(Features);
4315
4316 break;
4317 }
4318 }
4319 return false;
4320}
4321
Tim Northover3b0846e2014-05-24 12:50:23 +00004322/// parseDirectiveWord
4323/// ::= .word [ expression (, expression)* ]
4324bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004325 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00004326 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4327 for (;;) {
4328 const MCExpr *Value;
4329 if (getParser().parseExpression(Value))
4330 return true;
4331
Oliver Stannard09be0602015-11-16 16:22:47 +00004332 getParser().getStreamer().EmitValue(Value, Size, L);
Tim Northover3b0846e2014-05-24 12:50:23 +00004333
4334 if (getLexer().is(AsmToken::EndOfStatement))
4335 break;
4336
4337 // FIXME: Improve diagnostic.
4338 if (getLexer().isNot(AsmToken::Comma))
4339 return Error(L, "unexpected token in directive");
4340 Parser.Lex();
4341 }
4342 }
4343
4344 Parser.Lex();
4345 return false;
4346}
4347
Chad Rosierdcd2a302014-10-22 20:35:57 +00004348/// parseDirectiveInst
4349/// ::= .inst opcode [, ...]
4350bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004351 MCAsmParser &Parser = getParser();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004352 if (getLexer().is(AsmToken::EndOfStatement)) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004353 Error(Loc, "expected expression following directive");
4354 return false;
4355 }
4356
4357 for (;;) {
4358 const MCExpr *Expr;
4359
4360 if (getParser().parseExpression(Expr)) {
4361 Error(Loc, "expected expression");
4362 return false;
4363 }
4364
4365 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
4366 if (!Value) {
4367 Error(Loc, "expected constant expression");
4368 return false;
4369 }
4370
4371 getTargetStreamer().emitInst(Value->getValue());
4372
4373 if (getLexer().is(AsmToken::EndOfStatement))
4374 break;
4375
4376 if (getLexer().isNot(AsmToken::Comma)) {
4377 Error(Loc, "unexpected token in directive");
4378 return false;
4379 }
4380
4381 Parser.Lex(); // Eat comma.
4382 }
4383
4384 Parser.Lex();
4385 return false;
4386}
4387
Tim Northover3b0846e2014-05-24 12:50:23 +00004388// parseDirectiveTLSDescCall:
4389// ::= .tlsdesccall symbol
4390bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4391 StringRef Name;
4392 if (getParser().parseIdentifier(Name))
4393 return Error(L, "expected symbol after directive");
4394
Jim Grosbach6f482002015-05-18 18:43:14 +00004395 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004396 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4397 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004398
4399 MCInst Inst;
4400 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004401 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004402
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004403 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004404 return false;
4405}
4406
4407/// ::= .loh <lohName | lohId> label1, ..., labelN
4408/// The number of arguments depends on the loh identifier.
4409bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004410 MCLOHType Kind;
4411 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4412 if (getParser().getTok().isNot(AsmToken::Integer))
4413 return TokError("expected an identifier or a number in directive");
4414 // We successfully get a numeric value for the identifier.
4415 // Check if it is valid.
4416 int64_t Id = getParser().getTok().getIntVal();
Nirav Dave2364748a2016-09-16 18:30:20 +00004417 if (Id <= -1U && !isValidMCLOHType(Id)) {
4418 TokError("invalid numeric identifier in directive");
4419 return false;
4420 }
Alexey Samsonov700964e2014-08-29 22:34:28 +00004421 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004422 } else {
4423 StringRef Name = getTok().getIdentifier();
4424 // We successfully parse an identifier.
4425 // Check if it is a recognized one.
4426 int Id = MCLOHNameToId(Name);
4427
4428 if (Id == -1)
4429 return TokError("invalid identifier in directive");
4430 Kind = (MCLOHType)Id;
4431 }
4432 // Consume the identifier.
4433 Lex();
4434 // Get the number of arguments of this LOH.
4435 int NbArgs = MCLOHIdToNbArgs(Kind);
4436
4437 assert(NbArgs != -1 && "Invalid number of arguments");
4438
4439 SmallVector<MCSymbol *, 3> Args;
4440 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4441 StringRef Name;
4442 if (getParser().parseIdentifier(Name))
4443 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004444 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004445
4446 if (Idx + 1 == NbArgs)
4447 break;
4448 if (getLexer().isNot(AsmToken::Comma))
4449 return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
4450 Lex();
4451 }
4452 if (getLexer().isNot(AsmToken::EndOfStatement))
4453 return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
4454
4455 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4456 return false;
4457}
4458
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004459/// parseDirectiveLtorg
4460/// ::= .ltorg | .pool
4461bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
4462 getTargetStreamer().emitCurrentConstantPool();
4463 return false;
4464}
4465
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004466/// parseDirectiveReq
4467/// ::= name .req registername
4468bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004469 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004470 Parser.Lex(); // Eat the '.req' token.
4471 SMLoc SRegLoc = getLoc();
4472 unsigned RegNum = tryParseRegister();
4473 bool IsVector = false;
4474
4475 if (RegNum == static_cast<unsigned>(-1)) {
4476 StringRef Kind;
4477 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004478 if (!Kind.empty())
4479 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004480 IsVector = true;
4481 }
4482
Nirav Dave2364748a2016-09-16 18:30:20 +00004483 if (RegNum == static_cast<unsigned>(-1))
4484 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004485
4486 // Shouldn't be anything else.
Nirav Dave2364748a2016-09-16 18:30:20 +00004487 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
4488 return Error(Parser.getTok().getLoc(),
4489 "unexpected input in .req directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004490
4491 Parser.Lex(); // Consume the EndOfStatement
4492
4493 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004494 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004495 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4496
Nirav Dave2364748a2016-09-16 18:30:20 +00004497 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004498}
4499
4500/// parseDirectiveUneq
4501/// ::= .unreq registername
4502bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004503 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004504 if (Parser.getTok().isNot(AsmToken::Identifier)) {
4505 Error(Parser.getTok().getLoc(), "unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004506 return false;
4507 }
4508 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4509 Parser.Lex(); // Eat the identifier.
4510 return false;
4511}
4512
Tim Northover3b0846e2014-05-24 12:50:23 +00004513bool
4514AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4515 AArch64MCExpr::VariantKind &ELFRefKind,
4516 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4517 int64_t &Addend) {
4518 ELFRefKind = AArch64MCExpr::VK_INVALID;
4519 DarwinRefKind = MCSymbolRefExpr::VK_None;
4520 Addend = 0;
4521
4522 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4523 ELFRefKind = AE->getKind();
4524 Expr = AE->getSubExpr();
4525 }
4526
4527 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4528 if (SE) {
4529 // It's a simple symbol reference with no addend.
4530 DarwinRefKind = SE->getKind();
4531 return true;
4532 }
4533
4534 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4535 if (!BE)
4536 return false;
4537
4538 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4539 if (!SE)
4540 return false;
4541 DarwinRefKind = SE->getKind();
4542
4543 if (BE->getOpcode() != MCBinaryExpr::Add &&
4544 BE->getOpcode() != MCBinaryExpr::Sub)
4545 return false;
4546
4547 // See if the addend is is a constant, otherwise there's more going
4548 // on here than we can deal with.
4549 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4550 if (!AddendExpr)
4551 return false;
4552
4553 Addend = AddendExpr->getValue();
4554 if (BE->getOpcode() == MCBinaryExpr::Sub)
4555 Addend = -Addend;
4556
4557 // It's some symbol reference + a constant addend, but really
4558 // shouldn't use both Darwin and ELF syntax.
4559 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4560 DarwinRefKind == MCSymbolRefExpr::VK_None;
4561}
4562
4563/// Force static initialization.
4564extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004565 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4566 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4567 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004568}
4569
4570#define GET_REGISTER_MATCHER
4571#define GET_SUBTARGET_FEATURE_NAME
4572#define GET_MATCHER_IMPLEMENTATION
4573#include "AArch64GenAsmMatcher.inc"
4574
4575// Define this matcher function after the auto-generated include so we
4576// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004577unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004578 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004579 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004580 // If the kind is a token for a literal immediate, check if our asm
4581 // operand matches. This is for InstAliases which have a fixed-value
4582 // immediate in the syntax.
4583 int64_t ExpectedVal;
4584 switch (Kind) {
4585 default:
4586 return Match_InvalidOperand;
4587 case MCK__35_0:
4588 ExpectedVal = 0;
4589 break;
4590 case MCK__35_1:
4591 ExpectedVal = 1;
4592 break;
4593 case MCK__35_12:
4594 ExpectedVal = 12;
4595 break;
4596 case MCK__35_16:
4597 ExpectedVal = 16;
4598 break;
4599 case MCK__35_2:
4600 ExpectedVal = 2;
4601 break;
4602 case MCK__35_24:
4603 ExpectedVal = 24;
4604 break;
4605 case MCK__35_3:
4606 ExpectedVal = 3;
4607 break;
4608 case MCK__35_32:
4609 ExpectedVal = 32;
4610 break;
4611 case MCK__35_4:
4612 ExpectedVal = 4;
4613 break;
4614 case MCK__35_48:
4615 ExpectedVal = 48;
4616 break;
4617 case MCK__35_6:
4618 ExpectedVal = 6;
4619 break;
4620 case MCK__35_64:
4621 ExpectedVal = 64;
4622 break;
4623 case MCK__35_8:
4624 ExpectedVal = 8;
4625 break;
4626 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004627 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004630 if (!CE)
4631 return Match_InvalidOperand;
4632 if (CE->getValue() == ExpectedVal)
4633 return Match_Success;
4634 return Match_InvalidOperand;
4635}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004636
4637
Alex Bradbury58eba092016-11-01 16:32:05 +00004638OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004639AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4640
4641 SMLoc S = getLoc();
4642
4643 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4644 Error(S, "expected register");
4645 return MatchOperand_ParseFail;
4646 }
4647
4648 int FirstReg = tryParseRegister();
4649 if (FirstReg == -1) {
4650 return MatchOperand_ParseFail;
4651 }
4652 const MCRegisterClass &WRegClass =
4653 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4654 const MCRegisterClass &XRegClass =
4655 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4656
4657 bool isXReg = XRegClass.contains(FirstReg),
4658 isWReg = WRegClass.contains(FirstReg);
4659 if (!isXReg && !isWReg) {
4660 Error(S, "expected first even register of a "
4661 "consecutive same-size even/odd register pair");
4662 return MatchOperand_ParseFail;
4663 }
4664
4665 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4666 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4667
4668 if (FirstEncoding & 0x1) {
4669 Error(S, "expected first even register of a "
4670 "consecutive same-size even/odd register pair");
4671 return MatchOperand_ParseFail;
4672 }
4673
4674 SMLoc M = getLoc();
4675 if (getParser().getTok().isNot(AsmToken::Comma)) {
4676 Error(M, "expected comma");
4677 return MatchOperand_ParseFail;
4678 }
4679 // Eat the comma
4680 getParser().Lex();
4681
4682 SMLoc E = getLoc();
4683 int SecondReg = tryParseRegister();
4684 if (SecondReg ==-1) {
4685 return MatchOperand_ParseFail;
4686 }
4687
4688 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
4689 (isXReg && !XRegClass.contains(SecondReg)) ||
4690 (isWReg && !WRegClass.contains(SecondReg))) {
4691 Error(E,"expected second odd register of a "
4692 "consecutive same-size even/odd register pair");
4693 return MatchOperand_ParseFail;
4694 }
Joel Jones504bf332016-10-24 13:37:13 +00004695
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004696 unsigned Pair = 0;
4697 if(isXReg) {
4698 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4699 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4700 } else {
4701 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4702 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4703 }
4704
4705 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4706 getContext()));
4707
4708 return MatchOperand_Success;
4709}