blob: b86a283b40d493c6839558c54865445ac7b69d6f [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000018#include "llvm/ADT/SmallVector.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000019#include "llvm/ADT/STLExtras.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Tim Northover3b0846e2014-05-24 12:50:23 +000062class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000063private:
64 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000065
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000066 // Map of register aliases registers via the .req directive.
Eugene Zelenko049b0172017-01-06 00:30:53 +000067 StringMap<std::pair<bool, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000068
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000069 AArch64TargetStreamer &getTargetStreamer() {
70 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
71 return static_cast<AArch64TargetStreamer &>(TS);
72 }
73
Rafael Espindola961d4692014-11-11 05:18:41 +000074 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000075
76 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
77 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
78 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000079 unsigned matchRegisterNameAlias(StringRef Name, bool isVector);
Tim Northover3b0846e2014-05-24 12:50:23 +000080 int tryParseRegister();
81 int tryMatchVectorRegister(StringRef &Kind, bool expected);
82 bool parseRegister(OperandVector &Operands);
83 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
84 bool parseVectorList(OperandVector &Operands);
85 bool parseOperand(OperandVector &Operands, bool isCondCode,
86 bool invertCondCode);
87
Tim Northover3b0846e2014-05-24 12:50:23 +000088 bool showMatchError(SMLoc Loc, unsigned ErrCode);
89
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000090 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000091 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000092 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000093 bool parseDirectiveInst(SMLoc L);
94
Tim Northover3b0846e2014-05-24 12:50:23 +000095 bool parseDirectiveTLSDescCall(SMLoc L);
96
97 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000098 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000099
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000100 bool parseDirectiveReq(StringRef Name, SMLoc L);
101 bool parseDirectiveUnreq(SMLoc L);
102
Tim Northover3b0846e2014-05-24 12:50:23 +0000103 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
104 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
105 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000106 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000107 bool MatchingInlineAsm) override;
108/// @name Auto-generated Match Functions
109/// {
110
111#define GET_ASSEMBLER_HEADER
112#include "AArch64GenAsmMatcher.inc"
113
114 /// }
115
116 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
117 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
118 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
119 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
120 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
121 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000122 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000123 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
124 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
125 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
126 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
127 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
128 bool tryParseVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000129 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000130
131public:
132 enum AArch64MatchResultTy {
133 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
134#define GET_OPERAND_DIAGNOSTIC_TYPES
135#include "AArch64GenAsmMatcher.inc"
136 };
Joel Jones504bf332016-10-24 13:37:13 +0000137 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000138
Akira Hatanakab11ef082015-11-14 06:35:56 +0000139 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000140 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000141 : MCTargetAsmParser(Options, STI) {
Joel Jones504bf332016-10-24 13:37:13 +0000142 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000143 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000144 MCStreamer &S = getParser().getStreamer();
145 if (S.getTargetStreamer() == nullptr)
146 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000147
148 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000149 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000150 }
151
152 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
153 SMLoc NameLoc, OperandVector &Operands) override;
154 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
155 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000156 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000157 unsigned Kind) override;
158
159 static bool classifySymbolRef(const MCExpr *Expr,
160 AArch64MCExpr::VariantKind &ELFRefKind,
161 MCSymbolRefExpr::VariantKind &DarwinRefKind,
162 int64_t &Addend);
163};
Tim Northover3b0846e2014-05-24 12:50:23 +0000164
165/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
166/// instruction.
167class AArch64Operand : public MCParsedAsmOperand {
168private:
169 enum KindTy {
170 k_Immediate,
171 k_ShiftedImm,
172 k_CondCode,
173 k_Register,
174 k_VectorList,
175 k_VectorIndex,
176 k_Token,
177 k_SysReg,
178 k_SysCR,
179 k_Prefetch,
180 k_ShiftExtend,
181 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000182 k_Barrier,
183 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 } Kind;
185
186 SMLoc StartLoc, EndLoc;
187
188 struct TokOp {
189 const char *Data;
190 unsigned Length;
191 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
192 };
193
194 struct RegOp {
195 unsigned RegNum;
196 bool isVector;
197 };
198
199 struct VectorListOp {
200 unsigned RegNum;
201 unsigned Count;
202 unsigned NumElements;
203 unsigned ElementKind;
204 };
205
206 struct VectorIndexOp {
207 unsigned Val;
208 };
209
210 struct ImmOp {
211 const MCExpr *Val;
212 };
213
214 struct ShiftedImmOp {
215 const MCExpr *Val;
216 unsigned ShiftAmount;
217 };
218
219 struct CondCodeOp {
220 AArch64CC::CondCode Code;
221 };
222
223 struct FPImmOp {
224 unsigned Val; // Encoded 8-bit representation.
225 };
226
227 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000228 const char *Data;
229 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000230 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000231 };
232
233 struct SysRegOp {
234 const char *Data;
235 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000236 uint32_t MRSReg;
237 uint32_t MSRReg;
238 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000239 };
240
241 struct SysCRImmOp {
242 unsigned Val;
243 };
244
245 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000246 const char *Data;
247 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000248 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000249 };
250
Oliver Stannarda34e4702015-12-01 10:48:51 +0000251 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000252 const char *Data;
253 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000254 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000255 };
256
Tim Northover3b0846e2014-05-24 12:50:23 +0000257 struct ShiftExtendOp {
258 AArch64_AM::ShiftExtendType Type;
259 unsigned Amount;
260 bool HasExplicitAmount;
261 };
262
263 struct ExtendOp {
264 unsigned Val;
265 };
266
267 union {
268 struct TokOp Tok;
269 struct RegOp Reg;
270 struct VectorListOp VectorList;
271 struct VectorIndexOp VectorIndex;
272 struct ImmOp Imm;
273 struct ShiftedImmOp ShiftedImm;
274 struct CondCodeOp CondCode;
275 struct FPImmOp FPImm;
276 struct BarrierOp Barrier;
277 struct SysRegOp SysReg;
278 struct SysCRImmOp SysCRImm;
279 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000280 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000281 struct ShiftExtendOp ShiftExtend;
282 };
283
284 // Keep the MCContext around as the MCExprs may need manipulated during
285 // the add<>Operands() calls.
286 MCContext &Ctx;
287
David Blaikie960ea3f2014-06-08 16:18:35 +0000288public:
David Blaikie9f380a32015-03-16 18:06:57 +0000289 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000290
Tim Northover3b0846e2014-05-24 12:50:23 +0000291 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
292 Kind = o.Kind;
293 StartLoc = o.StartLoc;
294 EndLoc = o.EndLoc;
295 switch (Kind) {
296 case k_Token:
297 Tok = o.Tok;
298 break;
299 case k_Immediate:
300 Imm = o.Imm;
301 break;
302 case k_ShiftedImm:
303 ShiftedImm = o.ShiftedImm;
304 break;
305 case k_CondCode:
306 CondCode = o.CondCode;
307 break;
308 case k_FPImm:
309 FPImm = o.FPImm;
310 break;
311 case k_Barrier:
312 Barrier = o.Barrier;
313 break;
314 case k_Register:
315 Reg = o.Reg;
316 break;
317 case k_VectorList:
318 VectorList = o.VectorList;
319 break;
320 case k_VectorIndex:
321 VectorIndex = o.VectorIndex;
322 break;
323 case k_SysReg:
324 SysReg = o.SysReg;
325 break;
326 case k_SysCR:
327 SysCRImm = o.SysCRImm;
328 break;
329 case k_Prefetch:
330 Prefetch = o.Prefetch;
331 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000332 case k_PSBHint:
333 PSBHint = o.PSBHint;
334 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000335 case k_ShiftExtend:
336 ShiftExtend = o.ShiftExtend;
337 break;
338 }
339 }
340
341 /// getStartLoc - Get the location of the first token of this operand.
342 SMLoc getStartLoc() const override { return StartLoc; }
343 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000344 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000345
346 StringRef getToken() const {
347 assert(Kind == k_Token && "Invalid access!");
348 return StringRef(Tok.Data, Tok.Length);
349 }
350
351 bool isTokenSuffix() const {
352 assert(Kind == k_Token && "Invalid access!");
353 return Tok.IsSuffix;
354 }
355
356 const MCExpr *getImm() const {
357 assert(Kind == k_Immediate && "Invalid access!");
358 return Imm.Val;
359 }
360
361 const MCExpr *getShiftedImmVal() const {
362 assert(Kind == k_ShiftedImm && "Invalid access!");
363 return ShiftedImm.Val;
364 }
365
366 unsigned getShiftedImmShift() const {
367 assert(Kind == k_ShiftedImm && "Invalid access!");
368 return ShiftedImm.ShiftAmount;
369 }
370
371 AArch64CC::CondCode getCondCode() const {
372 assert(Kind == k_CondCode && "Invalid access!");
373 return CondCode.Code;
374 }
375
376 unsigned getFPImm() const {
377 assert(Kind == k_FPImm && "Invalid access!");
378 return FPImm.Val;
379 }
380
381 unsigned getBarrier() const {
382 assert(Kind == k_Barrier && "Invalid access!");
383 return Barrier.Val;
384 }
385
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000386 StringRef getBarrierName() const {
387 assert(Kind == k_Barrier && "Invalid access!");
388 return StringRef(Barrier.Data, Barrier.Length);
389 }
390
Tim Northover3b0846e2014-05-24 12:50:23 +0000391 unsigned getReg() const override {
392 assert(Kind == k_Register && "Invalid access!");
393 return Reg.RegNum;
394 }
395
396 unsigned getVectorListStart() const {
397 assert(Kind == k_VectorList && "Invalid access!");
398 return VectorList.RegNum;
399 }
400
401 unsigned getVectorListCount() const {
402 assert(Kind == k_VectorList && "Invalid access!");
403 return VectorList.Count;
404 }
405
406 unsigned getVectorIndex() const {
407 assert(Kind == k_VectorIndex && "Invalid access!");
408 return VectorIndex.Val;
409 }
410
411 StringRef getSysReg() const {
412 assert(Kind == k_SysReg && "Invalid access!");
413 return StringRef(SysReg.Data, SysReg.Length);
414 }
415
Tim Northover3b0846e2014-05-24 12:50:23 +0000416 unsigned getSysCR() const {
417 assert(Kind == k_SysCR && "Invalid access!");
418 return SysCRImm.Val;
419 }
420
421 unsigned getPrefetch() const {
422 assert(Kind == k_Prefetch && "Invalid access!");
423 return Prefetch.Val;
424 }
425
Oliver Stannarda34e4702015-12-01 10:48:51 +0000426 unsigned getPSBHint() const {
427 assert(Kind == k_PSBHint && "Invalid access!");
428 return PSBHint.Val;
429 }
430
431 StringRef getPSBHintName() const {
432 assert(Kind == k_PSBHint && "Invalid access!");
433 return StringRef(PSBHint.Data, PSBHint.Length);
434 }
435
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000436 StringRef getPrefetchName() const {
437 assert(Kind == k_Prefetch && "Invalid access!");
438 return StringRef(Prefetch.Data, Prefetch.Length);
439 }
440
Tim Northover3b0846e2014-05-24 12:50:23 +0000441 AArch64_AM::ShiftExtendType getShiftExtendType() const {
442 assert(Kind == k_ShiftExtend && "Invalid access!");
443 return ShiftExtend.Type;
444 }
445
446 unsigned getShiftExtendAmount() const {
447 assert(Kind == k_ShiftExtend && "Invalid access!");
448 return ShiftExtend.Amount;
449 }
450
451 bool hasShiftExtendAmount() const {
452 assert(Kind == k_ShiftExtend && "Invalid access!");
453 return ShiftExtend.HasExplicitAmount;
454 }
455
456 bool isImm() const override { return Kind == k_Immediate; }
457 bool isMem() const override { return false; }
458 bool isSImm9() const {
459 if (!isImm())
460 return false;
461 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
462 if (!MCE)
463 return false;
464 int64_t Val = MCE->getValue();
465 return (Val >= -256 && Val < 256);
466 }
467 bool isSImm7s4() const {
468 if (!isImm())
469 return false;
470 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
471 if (!MCE)
472 return false;
473 int64_t Val = MCE->getValue();
474 return (Val >= -256 && Val <= 252 && (Val & 3) == 0);
475 }
476 bool isSImm7s8() const {
477 if (!isImm())
478 return false;
479 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
480 if (!MCE)
481 return false;
482 int64_t Val = MCE->getValue();
483 return (Val >= -512 && Val <= 504 && (Val & 7) == 0);
484 }
485 bool isSImm7s16() const {
486 if (!isImm())
487 return false;
488 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
489 if (!MCE)
490 return false;
491 int64_t Val = MCE->getValue();
492 return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
493 }
494
495 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
496 AArch64MCExpr::VariantKind ELFRefKind;
497 MCSymbolRefExpr::VariantKind DarwinRefKind;
498 int64_t Addend;
499 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
500 Addend)) {
501 // If we don't understand the expression, assume the best and
502 // let the fixup and relocation code deal with it.
503 return true;
504 }
505
506 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
507 ELFRefKind == AArch64MCExpr::VK_LO12 ||
508 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
509 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
510 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
511 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
512 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
513 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
514 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
515 // Note that we don't range-check the addend. It's adjusted modulo page
516 // size when converted, so there is no "out of range" condition when using
517 // @pageoff.
518 return Addend >= 0 && (Addend % Scale) == 0;
519 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
520 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
521 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
522 return Addend == 0;
523 }
524
525 return false;
526 }
527
528 template <int Scale> bool isUImm12Offset() const {
529 if (!isImm())
530 return false;
531
532 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
533 if (!MCE)
534 return isSymbolicUImm12Offset(getImm(), Scale);
535
536 int64_t Val = MCE->getValue();
537 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
538 }
539
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000540 bool isImm0_1() const {
541 if (!isImm())
542 return false;
543 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
544 if (!MCE)
545 return false;
546 int64_t Val = MCE->getValue();
547 return (Val >= 0 && Val < 2);
548 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000549
Tim Northover3b0846e2014-05-24 12:50:23 +0000550 bool isImm0_7() const {
551 if (!isImm())
552 return false;
553 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
554 if (!MCE)
555 return false;
556 int64_t Val = MCE->getValue();
557 return (Val >= 0 && Val < 8);
558 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000559
Tim Northover3b0846e2014-05-24 12:50:23 +0000560 bool isImm1_8() const {
561 if (!isImm())
562 return false;
563 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
564 if (!MCE)
565 return false;
566 int64_t Val = MCE->getValue();
567 return (Val > 0 && Val < 9);
568 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000569
Tim Northover3b0846e2014-05-24 12:50:23 +0000570 bool isImm0_15() const {
571 if (!isImm())
572 return false;
573 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
574 if (!MCE)
575 return false;
576 int64_t Val = MCE->getValue();
577 return (Val >= 0 && Val < 16);
578 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000579
Tim Northover3b0846e2014-05-24 12:50:23 +0000580 bool isImm1_16() const {
581 if (!isImm())
582 return false;
583 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
584 if (!MCE)
585 return false;
586 int64_t Val = MCE->getValue();
587 return (Val > 0 && Val < 17);
588 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000589
Tim Northover3b0846e2014-05-24 12:50:23 +0000590 bool isImm0_31() 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 >= 0 && Val < 32);
598 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000599
Tim Northover3b0846e2014-05-24 12:50:23 +0000600 bool isImm1_31() const {
601 if (!isImm())
602 return false;
603 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
604 if (!MCE)
605 return false;
606 int64_t Val = MCE->getValue();
607 return (Val >= 1 && Val < 32);
608 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000609
Tim Northover3b0846e2014-05-24 12:50:23 +0000610 bool isImm1_32() const {
611 if (!isImm())
612 return false;
613 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
614 if (!MCE)
615 return false;
616 int64_t Val = MCE->getValue();
617 return (Val >= 1 && Val < 33);
618 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000619
Tim Northover3b0846e2014-05-24 12:50:23 +0000620 bool isImm0_63() const {
621 if (!isImm())
622 return false;
623 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
624 if (!MCE)
625 return false;
626 int64_t Val = MCE->getValue();
627 return (Val >= 0 && Val < 64);
628 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000629
Tim Northover3b0846e2014-05-24 12:50:23 +0000630 bool isImm1_63() const {
631 if (!isImm())
632 return false;
633 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
634 if (!MCE)
635 return false;
636 int64_t Val = MCE->getValue();
637 return (Val >= 1 && Val < 64);
638 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000639
Tim Northover3b0846e2014-05-24 12:50:23 +0000640 bool isImm1_64() const {
641 if (!isImm())
642 return false;
643 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
644 if (!MCE)
645 return false;
646 int64_t Val = MCE->getValue();
647 return (Val >= 1 && Val < 65);
648 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000649
Tim Northover3b0846e2014-05-24 12:50:23 +0000650 bool isImm0_127() const {
651 if (!isImm())
652 return false;
653 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
654 if (!MCE)
655 return false;
656 int64_t Val = MCE->getValue();
657 return (Val >= 0 && Val < 128);
658 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000659
Tim Northover3b0846e2014-05-24 12:50:23 +0000660 bool isImm0_255() const {
661 if (!isImm())
662 return false;
663 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
664 if (!MCE)
665 return false;
666 int64_t Val = MCE->getValue();
667 return (Val >= 0 && Val < 256);
668 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000669
Tim Northover3b0846e2014-05-24 12:50:23 +0000670 bool isImm0_65535() const {
671 if (!isImm())
672 return false;
673 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
674 if (!MCE)
675 return false;
676 int64_t Val = MCE->getValue();
677 return (Val >= 0 && Val < 65536);
678 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000679
Tim Northover3b0846e2014-05-24 12:50:23 +0000680 bool isImm32_63() const {
681 if (!isImm())
682 return false;
683 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
684 if (!MCE)
685 return false;
686 int64_t Val = MCE->getValue();
687 return (Val >= 32 && Val < 64);
688 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000689
Tim Northover3b0846e2014-05-24 12:50:23 +0000690 bool isLogicalImm32() const {
691 if (!isImm())
692 return false;
693 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
694 if (!MCE)
695 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000696 int64_t Val = MCE->getValue();
697 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
698 return false;
699 Val &= 0xFFFFFFFF;
700 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000701 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000702
Tim Northover3b0846e2014-05-24 12:50:23 +0000703 bool isLogicalImm64() const {
704 if (!isImm())
705 return false;
706 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
707 if (!MCE)
708 return false;
709 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
710 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000711
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000712 bool isLogicalImm32Not() const {
713 if (!isImm())
714 return false;
715 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
716 if (!MCE)
717 return false;
718 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
719 return AArch64_AM::isLogicalImmediate(Val, 32);
720 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000721
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000722 bool isLogicalImm64Not() const {
723 if (!isImm())
724 return false;
725 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
726 if (!MCE)
727 return false;
728 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
729 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000730
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000732
Tim Northover3b0846e2014-05-24 12:50:23 +0000733 bool isAddSubImm() const {
734 if (!isShiftedImm() && !isImm())
735 return false;
736
737 const MCExpr *Expr;
738
739 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
740 if (isShiftedImm()) {
741 unsigned Shift = ShiftedImm.ShiftAmount;
742 Expr = ShiftedImm.Val;
743 if (Shift != 0 && Shift != 12)
744 return false;
745 } else {
746 Expr = getImm();
747 }
748
749 AArch64MCExpr::VariantKind ELFRefKind;
750 MCSymbolRefExpr::VariantKind DarwinRefKind;
751 int64_t Addend;
752 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
753 DarwinRefKind, Addend)) {
754 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
755 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
756 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
757 || ELFRefKind == AArch64MCExpr::VK_LO12
758 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
759 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
760 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
761 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
762 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
763 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
764 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
765 }
766
Diana Picusc93518d2016-10-11 09:17:47 +0000767 // If it's a constant, it should be a real immediate in range:
768 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
769 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
770
771 // If it's an expression, we hope for the best and let the fixup/relocation
772 // code deal with it.
773 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000774 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000775
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000776 bool isAddSubImmNeg() const {
777 if (!isShiftedImm() && !isImm())
778 return false;
779
780 const MCExpr *Expr;
781
782 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
783 if (isShiftedImm()) {
784 unsigned Shift = ShiftedImm.ShiftAmount;
785 Expr = ShiftedImm.Val;
786 if (Shift != 0 && Shift != 12)
787 return false;
788 } else
789 Expr = getImm();
790
791 // Otherwise it should be a real negative immediate in range:
792 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
793 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
794 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000795
Tim Northover3b0846e2014-05-24 12:50:23 +0000796 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000797
Tim Northover3b0846e2014-05-24 12:50:23 +0000798 bool isSIMDImmType10() const {
799 if (!isImm())
800 return false;
801 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
802 if (!MCE)
803 return false;
804 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
805 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000806
Tim Northover3b0846e2014-05-24 12:50:23 +0000807 bool isBranchTarget26() const {
808 if (!isImm())
809 return false;
810 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
811 if (!MCE)
812 return true;
813 int64_t Val = MCE->getValue();
814 if (Val & 0x3)
815 return false;
816 return (Val >= -(0x2000000 << 2) && Val <= (0x1ffffff << 2));
817 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000818
Tim Northover3b0846e2014-05-24 12:50:23 +0000819 bool isPCRelLabel19() const {
820 if (!isImm())
821 return false;
822 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
823 if (!MCE)
824 return true;
825 int64_t Val = MCE->getValue();
826 if (Val & 0x3)
827 return false;
828 return (Val >= -(0x40000 << 2) && Val <= (0x3ffff << 2));
829 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000830
Tim Northover3b0846e2014-05-24 12:50:23 +0000831 bool isBranchTarget14() const {
832 if (!isImm())
833 return false;
834 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
835 if (!MCE)
836 return true;
837 int64_t Val = MCE->getValue();
838 if (Val & 0x3)
839 return false;
840 return (Val >= -(0x2000 << 2) && Val <= (0x1fff << 2));
841 }
842
843 bool
844 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
845 if (!isImm())
846 return false;
847
848 AArch64MCExpr::VariantKind ELFRefKind;
849 MCSymbolRefExpr::VariantKind DarwinRefKind;
850 int64_t Addend;
851 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
852 DarwinRefKind, Addend)) {
853 return false;
854 }
855 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
856 return false;
857
858 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
859 if (ELFRefKind == AllowedModifiers[i])
860 return Addend == 0;
861 }
862
863 return false;
864 }
865
866 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000867 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000868 }
869
870 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000871 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
872 AArch64MCExpr::VK_TPREL_G2,
873 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000874 }
875
876 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000877 return isMovWSymbol({
878 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000879 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
880 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000881 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000882 }
883
884 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000885 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
886 AArch64MCExpr::VK_TPREL_G0,
887 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000888 }
889
890 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000891 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000892 }
893
894 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000895 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000896 }
897
898 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000899 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
900 AArch64MCExpr::VK_TPREL_G1_NC,
901 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000902 }
903
904 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000905 return isMovWSymbol(
906 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
907 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000908 }
909
910 template<int RegWidth, int Shift>
911 bool isMOVZMovAlias() const {
912 if (!isImm()) return false;
913
914 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
915 if (!CE) return false;
916 uint64_t Value = CE->getValue();
917
Tim Northoverdaa1c012016-06-16 01:42:25 +0000918 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000919 }
920
921 template<int RegWidth, int Shift>
922 bool isMOVNMovAlias() const {
923 if (!isImm()) return false;
924
925 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
926 if (!CE) return false;
927 uint64_t Value = CE->getValue();
928
Tim Northoverdaa1c012016-06-16 01:42:25 +0000929 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000930 }
931
932 bool isFPImm() const { return Kind == k_FPImm; }
933 bool isBarrier() const { return Kind == k_Barrier; }
934 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000935
Tim Northover3b0846e2014-05-24 12:50:23 +0000936 bool isMRSSystemRegister() const {
937 if (!isSysReg()) return false;
938
Tim Northover7cd58932015-01-22 17:23:04 +0000939 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000940 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000941
Tim Northover3b0846e2014-05-24 12:50:23 +0000942 bool isMSRSystemRegister() const {
943 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000944 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000945 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000946
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000947 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000948 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000949 return (SysReg.PStateField == AArch64PState::PAN ||
950 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000951 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000952
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000953 bool isSystemPStateFieldWithImm0_15() const {
954 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000955 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000956 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000957
Tim Northover3b0846e2014-05-24 12:50:23 +0000958 bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
959 bool isVectorReg() const { return Kind == k_Register && Reg.isVector; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000960
Tim Northover3b0846e2014-05-24 12:50:23 +0000961 bool isVectorRegLo() const {
962 return Kind == k_Register && Reg.isVector &&
963 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
964 Reg.RegNum);
965 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000966
Tim Northover3b0846e2014-05-24 12:50:23 +0000967 bool isGPR32as64() const {
968 return Kind == k_Register && !Reg.isVector &&
969 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
970 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000971
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000972 bool isWSeqPair() const {
973 return Kind == k_Register && !Reg.isVector &&
974 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
975 Reg.RegNum);
976 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000977
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000978 bool isXSeqPair() const {
979 return Kind == k_Register && !Reg.isVector &&
980 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
981 Reg.RegNum);
982 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000983
984 bool isGPR64sp0() const {
985 return Kind == k_Register && !Reg.isVector &&
986 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
987 }
988
989 /// Is this a vector list with the type implicit (presumably attached to the
990 /// instruction itself)?
991 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
992 return Kind == k_VectorList && VectorList.Count == NumRegs &&
993 !VectorList.ElementKind;
994 }
995
996 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
997 bool isTypedVectorList() const {
998 if (Kind != k_VectorList)
999 return false;
1000 if (VectorList.Count != NumRegs)
1001 return false;
1002 if (VectorList.ElementKind != ElementKind)
1003 return false;
1004 return VectorList.NumElements == NumElements;
1005 }
1006
1007 bool isVectorIndex1() const {
1008 return Kind == k_VectorIndex && VectorIndex.Val == 1;
1009 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001010
Tim Northover3b0846e2014-05-24 12:50:23 +00001011 bool isVectorIndexB() const {
1012 return Kind == k_VectorIndex && VectorIndex.Val < 16;
1013 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001014
Tim Northover3b0846e2014-05-24 12:50:23 +00001015 bool isVectorIndexH() const {
1016 return Kind == k_VectorIndex && VectorIndex.Val < 8;
1017 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001018
Tim Northover3b0846e2014-05-24 12:50:23 +00001019 bool isVectorIndexS() const {
1020 return Kind == k_VectorIndex && VectorIndex.Val < 4;
1021 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001022
Tim Northover3b0846e2014-05-24 12:50:23 +00001023 bool isVectorIndexD() const {
1024 return Kind == k_VectorIndex && VectorIndex.Val < 2;
1025 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001026
Tim Northover3b0846e2014-05-24 12:50:23 +00001027 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001028
Tim Northover3b0846e2014-05-24 12:50:23 +00001029 bool isTokenEqual(StringRef Str) const {
1030 return Kind == k_Token && getToken() == Str;
1031 }
1032 bool isSysCR() const { return Kind == k_SysCR; }
1033 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001034 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001035 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1036 bool isShifter() const {
1037 if (!isShiftExtend())
1038 return false;
1039
1040 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1041 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1042 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1043 ST == AArch64_AM::MSL);
1044 }
1045 bool isExtend() const {
1046 if (!isShiftExtend())
1047 return false;
1048
1049 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1050 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1051 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1052 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1053 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1054 ET == AArch64_AM::LSL) &&
1055 getShiftExtendAmount() <= 4;
1056 }
1057
1058 bool isExtend64() const {
1059 if (!isExtend())
1060 return false;
1061 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1062 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1063 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1064 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001065
Tim Northover3b0846e2014-05-24 12:50:23 +00001066 bool isExtendLSL64() const {
1067 if (!isExtend())
1068 return false;
1069 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1070 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1071 ET == AArch64_AM::LSL) &&
1072 getShiftExtendAmount() <= 4;
1073 }
1074
1075 template<int Width> bool isMemXExtend() const {
1076 if (!isExtend())
1077 return false;
1078 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1079 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1080 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1081 getShiftExtendAmount() == 0);
1082 }
1083
1084 template<int Width> bool isMemWExtend() const {
1085 if (!isExtend())
1086 return false;
1087 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1088 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1089 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1090 getShiftExtendAmount() == 0);
1091 }
1092
1093 template <unsigned width>
1094 bool isArithmeticShifter() const {
1095 if (!isShifter())
1096 return false;
1097
1098 // An arithmetic shifter is LSL, LSR, or ASR.
1099 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1100 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1101 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1102 }
1103
1104 template <unsigned width>
1105 bool isLogicalShifter() const {
1106 if (!isShifter())
1107 return false;
1108
1109 // A logical shifter is LSL, LSR, ASR or ROR.
1110 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1111 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1112 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1113 getShiftExtendAmount() < width;
1114 }
1115
1116 bool isMovImm32Shifter() const {
1117 if (!isShifter())
1118 return false;
1119
1120 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1121 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1122 if (ST != AArch64_AM::LSL)
1123 return false;
1124 uint64_t Val = getShiftExtendAmount();
1125 return (Val == 0 || Val == 16);
1126 }
1127
1128 bool isMovImm64Shifter() const {
1129 if (!isShifter())
1130 return false;
1131
1132 // A MOVi shifter is LSL of 0 or 16.
1133 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1134 if (ST != AArch64_AM::LSL)
1135 return false;
1136 uint64_t Val = getShiftExtendAmount();
1137 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1138 }
1139
1140 bool isLogicalVecShifter() const {
1141 if (!isShifter())
1142 return false;
1143
1144 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1145 unsigned Shift = getShiftExtendAmount();
1146 return getShiftExtendType() == AArch64_AM::LSL &&
1147 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1148 }
1149
1150 bool isLogicalVecHalfWordShifter() const {
1151 if (!isLogicalVecShifter())
1152 return false;
1153
1154 // A logical vector shifter is a left shift by 0 or 8.
1155 unsigned Shift = getShiftExtendAmount();
1156 return getShiftExtendType() == AArch64_AM::LSL &&
1157 (Shift == 0 || Shift == 8);
1158 }
1159
1160 bool isMoveVecShifter() const {
1161 if (!isShiftExtend())
1162 return false;
1163
1164 // A logical vector shifter is a left shift by 8 or 16.
1165 unsigned Shift = getShiftExtendAmount();
1166 return getShiftExtendType() == AArch64_AM::MSL &&
1167 (Shift == 8 || Shift == 16);
1168 }
1169
1170 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1171 // to LDUR/STUR when the offset is not legal for the former but is for
1172 // the latter. As such, in addition to checking for being a legal unscaled
1173 // address, also check that it is not a legal scaled address. This avoids
1174 // ambiguity in the matcher.
1175 template<int Width>
1176 bool isSImm9OffsetFB() const {
1177 return isSImm9() && !isUImm12Offset<Width / 8>();
1178 }
1179
1180 bool isAdrpLabel() const {
1181 // Validation was handled during parsing, so we just sanity check that
1182 // something didn't go haywire.
1183 if (!isImm())
1184 return false;
1185
1186 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1187 int64_t Val = CE->getValue();
1188 int64_t Min = - (4096 * (1LL << (21 - 1)));
1189 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1190 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1191 }
1192
1193 return true;
1194 }
1195
1196 bool isAdrLabel() const {
1197 // Validation was handled during parsing, so we just sanity check that
1198 // something didn't go haywire.
1199 if (!isImm())
1200 return false;
1201
1202 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1203 int64_t Val = CE->getValue();
1204 int64_t Min = - (1LL << (21 - 1));
1205 int64_t Max = ((1LL << (21 - 1)) - 1);
1206 return Val >= Min && Val <= Max;
1207 }
1208
1209 return true;
1210 }
1211
1212 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1213 // Add as immediates when possible. Null MCExpr = 0.
1214 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001215 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001216 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001217 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001218 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001219 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001220 }
1221
1222 void addRegOperands(MCInst &Inst, unsigned N) const {
1223 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001224 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001225 }
1226
1227 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1228 assert(N == 1 && "Invalid number of operands!");
1229 assert(
1230 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1231
1232 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1233 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1234 RI->getEncodingValue(getReg()));
1235
Jim Grosbache9119e42015-05-13 18:37:00 +00001236 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001237 }
1238
1239 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1240 assert(N == 1 && "Invalid number of operands!");
1241 assert(
1242 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001243 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001244 }
1245
1246 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1247 assert(N == 1 && "Invalid number of operands!");
1248 assert(
1249 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001250 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001251 }
1252
1253 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1254 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001255 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001256 }
1257
1258 template <unsigned NumRegs>
1259 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001261 static const unsigned FirstRegs[] = { AArch64::D0,
1262 AArch64::D0_D1,
1263 AArch64::D0_D1_D2,
1264 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001265 unsigned FirstReg = FirstRegs[NumRegs - 1];
1266
1267 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001268 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001269 }
1270
1271 template <unsigned NumRegs>
1272 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001274 static const unsigned FirstRegs[] = { AArch64::Q0,
1275 AArch64::Q0_Q1,
1276 AArch64::Q0_Q1_Q2,
1277 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001278 unsigned FirstReg = FirstRegs[NumRegs - 1];
1279
1280 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001281 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001282 }
1283
1284 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1285 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001286 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001287 }
1288
1289 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001291 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001292 }
1293
1294 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1295 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001296 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001297 }
1298
1299 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1300 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001301 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001302 }
1303
1304 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1305 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001306 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001307 }
1308
1309 void addImmOperands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
1311 // If this is a pageoff symrefexpr with an addend, adjust the addend
1312 // to be only the page-offset portion. Otherwise, just add the expr
1313 // as-is.
1314 addExpr(Inst, getImm());
1315 }
1316
1317 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1318 assert(N == 2 && "Invalid number of operands!");
1319 if (isShiftedImm()) {
1320 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001321 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001322 } else {
1323 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001324 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001325 }
1326 }
1327
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001328 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 2 && "Invalid number of operands!");
1330
1331 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1332 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1333 int64_t Val = -CE->getValue();
1334 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1335
1336 Inst.addOperand(MCOperand::createImm(Val));
1337 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1338 }
1339
Tim Northover3b0846e2014-05-24 12:50:23 +00001340 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001342 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001343 }
1344
1345 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1346 assert(N == 1 && "Invalid number of operands!");
1347 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1348 if (!MCE)
1349 addExpr(Inst, getImm());
1350 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001351 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001352 }
1353
1354 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1355 addImmOperands(Inst, N);
1356 }
1357
1358 template<int Scale>
1359 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1360 assert(N == 1 && "Invalid number of operands!");
1361 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1362
1363 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001364 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001365 return;
1366 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001367 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001368 }
1369
1370 void addSImm9Operands(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 addSImm7s4Operands(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() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001380 }
1381
1382 void addSImm7s8Operands(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() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001386 }
1387
1388 void addSImm7s16Operands(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() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001392 }
1393
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001394 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1395 assert(N == 1 && "Invalid number of operands!");
1396 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1397 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1398 }
1399
Tim Northover3b0846e2014-05-24 12:50:23 +00001400 void addImm0_7Operands(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 addImm1_8Operands(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_15Operands(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 addImm1_16Operands(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());
Tim Northover3b0846e2014-05-24 12:50:23 +00001421 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001422 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001423 }
1424
1425 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001427 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 }
1430
1431 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1432 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001433 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001434 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001435 }
1436
1437 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1438 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001439 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001440 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001441 }
1442
1443 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1444 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001445 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001446 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001447 }
1448
1449 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001451 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001452 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 }
1454
1455 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001457 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001458 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001459 }
1460
1461 void addImm0_127Operands(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());
Jim Grosbache9119e42015-05-13 18:37:00 +00001464 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001465 }
1466
1467 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001469 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001470 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001471 }
1472
1473 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001475 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001476 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001477 }
1478
1479 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001481 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001482 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001483 }
1484
1485 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1486 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001487 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001488 uint64_t encoding =
1489 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001490 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001491 }
1492
1493 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1494 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001495 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001496 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001497 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001498 }
1499
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001500 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1501 assert(N == 1 && "Invalid number of operands!");
1502 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1503 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1504 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001505 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001506 }
1507
1508 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1509 assert(N == 1 && "Invalid number of operands!");
1510 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1511 uint64_t encoding =
1512 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001513 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001514 }
1515
Tim Northover3b0846e2014-05-24 12:50:23 +00001516 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001518 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001519 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001520 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001521 }
1522
1523 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1524 // Branch operands don't encode the low bits, so shift them off
1525 // here. If it's a label, however, just put it on directly as there's
1526 // not enough information now to do anything.
1527 assert(N == 1 && "Invalid number of operands!");
1528 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1529 if (!MCE) {
1530 addExpr(Inst, getImm());
1531 return;
1532 }
1533 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001534 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001535 }
1536
1537 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1538 // Branch operands don't encode the low bits, so shift them off
1539 // here. If it's a label, however, just put it on directly as there's
1540 // not enough information now to do anything.
1541 assert(N == 1 && "Invalid number of operands!");
1542 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1543 if (!MCE) {
1544 addExpr(Inst, getImm());
1545 return;
1546 }
1547 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001548 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001549 }
1550
1551 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1552 // Branch operands don't encode the low bits, so shift them off
1553 // here. If it's a label, however, just put it on directly as there's
1554 // not enough information now to do anything.
1555 assert(N == 1 && "Invalid number of operands!");
1556 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1557 if (!MCE) {
1558 addExpr(Inst, getImm());
1559 return;
1560 }
1561 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001562 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001563 }
1564
1565 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001567 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001568 }
1569
1570 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1571 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001572 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001573 }
1574
1575 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577
Jim Grosbache9119e42015-05-13 18:37:00 +00001578 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001579 }
1580
1581 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1582 assert(N == 1 && "Invalid number of operands!");
1583
Jim Grosbache9119e42015-05-13 18:37:00 +00001584 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001585 }
1586
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001587 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589
1590 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1591 }
1592
1593 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001594 assert(N == 1 && "Invalid number of operands!");
1595
Jim Grosbache9119e42015-05-13 18:37:00 +00001596 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001597 }
1598
1599 void addSysCROperands(MCInst &Inst, unsigned N) const {
1600 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001601 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001602 }
1603
1604 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1605 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001606 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001607 }
1608
Oliver Stannarda34e4702015-12-01 10:48:51 +00001609 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1610 assert(N == 1 && "Invalid number of operands!");
1611 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1612 }
1613
Tim Northover3b0846e2014-05-24 12:50:23 +00001614 void addShifterOperands(MCInst &Inst, unsigned N) const {
1615 assert(N == 1 && "Invalid number of operands!");
1616 unsigned Imm =
1617 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001618 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001619 }
1620
1621 void addExtendOperands(MCInst &Inst, unsigned N) const {
1622 assert(N == 1 && "Invalid number of operands!");
1623 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1624 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1625 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001626 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001627 }
1628
1629 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1630 assert(N == 1 && "Invalid number of operands!");
1631 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1632 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1633 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001634 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001635 }
1636
1637 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1638 assert(N == 2 && "Invalid number of operands!");
1639 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1640 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001641 Inst.addOperand(MCOperand::createImm(IsSigned));
1642 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001643 }
1644
1645 // For 8-bit load/store instructions with a register offset, both the
1646 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1647 // they're disambiguated by whether the shift was explicit or implicit rather
1648 // than its size.
1649 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1650 assert(N == 2 && "Invalid number of operands!");
1651 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1652 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001653 Inst.addOperand(MCOperand::createImm(IsSigned));
1654 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001655 }
1656
1657 template<int Shift>
1658 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1659 assert(N == 1 && "Invalid number of operands!");
1660
1661 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1662 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001663 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001664 }
1665
1666 template<int Shift>
1667 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1668 assert(N == 1 && "Invalid number of operands!");
1669
1670 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1671 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001672 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001673 }
1674
1675 void print(raw_ostream &OS) const override;
1676
David Blaikie960ea3f2014-06-08 16:18:35 +00001677 static std::unique_ptr<AArch64Operand>
1678 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1679 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001680 Op->Tok.Data = Str.data();
1681 Op->Tok.Length = Str.size();
1682 Op->Tok.IsSuffix = IsSuffix;
1683 Op->StartLoc = S;
1684 Op->EndLoc = S;
1685 return Op;
1686 }
1687
David Blaikie960ea3f2014-06-08 16:18:35 +00001688 static std::unique_ptr<AArch64Operand>
1689 CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
1690 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001691 Op->Reg.RegNum = RegNum;
1692 Op->Reg.isVector = isVector;
1693 Op->StartLoc = S;
1694 Op->EndLoc = E;
1695 return Op;
1696 }
1697
David Blaikie960ea3f2014-06-08 16:18:35 +00001698 static std::unique_ptr<AArch64Operand>
1699 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1700 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1701 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001702 Op->VectorList.RegNum = RegNum;
1703 Op->VectorList.Count = Count;
1704 Op->VectorList.NumElements = NumElements;
1705 Op->VectorList.ElementKind = ElementKind;
1706 Op->StartLoc = S;
1707 Op->EndLoc = E;
1708 return Op;
1709 }
1710
David Blaikie960ea3f2014-06-08 16:18:35 +00001711 static std::unique_ptr<AArch64Operand>
1712 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1713 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001714 Op->VectorIndex.Val = Idx;
1715 Op->StartLoc = S;
1716 Op->EndLoc = E;
1717 return Op;
1718 }
1719
David Blaikie960ea3f2014-06-08 16:18:35 +00001720 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1721 SMLoc E, MCContext &Ctx) {
1722 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001723 Op->Imm.Val = Val;
1724 Op->StartLoc = S;
1725 Op->EndLoc = E;
1726 return Op;
1727 }
1728
David Blaikie960ea3f2014-06-08 16:18:35 +00001729 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1730 unsigned ShiftAmount,
1731 SMLoc S, SMLoc E,
1732 MCContext &Ctx) {
1733 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001734 Op->ShiftedImm .Val = Val;
1735 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1736 Op->StartLoc = S;
1737 Op->EndLoc = E;
1738 return Op;
1739 }
1740
David Blaikie960ea3f2014-06-08 16:18:35 +00001741 static std::unique_ptr<AArch64Operand>
1742 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1743 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001744 Op->CondCode.Code = Code;
1745 Op->StartLoc = S;
1746 Op->EndLoc = E;
1747 return Op;
1748 }
1749
David Blaikie960ea3f2014-06-08 16:18:35 +00001750 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1751 MCContext &Ctx) {
1752 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001753 Op->FPImm.Val = Val;
1754 Op->StartLoc = S;
1755 Op->EndLoc = S;
1756 return Op;
1757 }
1758
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001759 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1760 StringRef Str,
1761 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001762 MCContext &Ctx) {
1763 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001764 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001765 Op->Barrier.Data = Str.data();
1766 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001767 Op->StartLoc = S;
1768 Op->EndLoc = S;
1769 return Op;
1770 }
1771
Tim Northover7cd58932015-01-22 17:23:04 +00001772 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1773 uint32_t MRSReg,
1774 uint32_t MSRReg,
1775 uint32_t PStateField,
1776 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001777 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001778 Op->SysReg.Data = Str.data();
1779 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001780 Op->SysReg.MRSReg = MRSReg;
1781 Op->SysReg.MSRReg = MSRReg;
1782 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001783 Op->StartLoc = S;
1784 Op->EndLoc = S;
1785 return Op;
1786 }
1787
David Blaikie960ea3f2014-06-08 16:18:35 +00001788 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1789 SMLoc E, MCContext &Ctx) {
1790 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001791 Op->SysCRImm.Val = Val;
1792 Op->StartLoc = S;
1793 Op->EndLoc = E;
1794 return Op;
1795 }
1796
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001797 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1798 StringRef Str,
1799 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001800 MCContext &Ctx) {
1801 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001802 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001803 Op->Barrier.Data = Str.data();
1804 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001805 Op->StartLoc = S;
1806 Op->EndLoc = S;
1807 return Op;
1808 }
1809
Oliver Stannarda34e4702015-12-01 10:48:51 +00001810 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1811 StringRef Str,
1812 SMLoc S,
1813 MCContext &Ctx) {
1814 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1815 Op->PSBHint.Val = Val;
1816 Op->PSBHint.Data = Str.data();
1817 Op->PSBHint.Length = Str.size();
1818 Op->StartLoc = S;
1819 Op->EndLoc = S;
1820 return Op;
1821 }
1822
David Blaikie960ea3f2014-06-08 16:18:35 +00001823 static std::unique_ptr<AArch64Operand>
1824 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1825 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1826 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001827 Op->ShiftExtend.Type = ShOp;
1828 Op->ShiftExtend.Amount = Val;
1829 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1830 Op->StartLoc = S;
1831 Op->EndLoc = E;
1832 return Op;
1833 }
1834};
1835
1836} // end anonymous namespace.
1837
1838void AArch64Operand::print(raw_ostream &OS) const {
1839 switch (Kind) {
1840 case k_FPImm:
1841 OS << "<fpimm " << getFPImm() << "("
1842 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1843 break;
1844 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001845 StringRef Name = getBarrierName();
1846 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001847 OS << "<barrier " << Name << ">";
1848 else
1849 OS << "<barrier invalid #" << getBarrier() << ">";
1850 break;
1851 }
1852 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001853 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001854 break;
1855 case k_ShiftedImm: {
1856 unsigned Shift = getShiftedImmShift();
1857 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001858 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001859 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1860 break;
1861 }
1862 case k_CondCode:
1863 OS << "<condcode " << getCondCode() << ">";
1864 break;
1865 case k_Register:
1866 OS << "<register " << getReg() << ">";
1867 break;
1868 case k_VectorList: {
1869 OS << "<vectorlist ";
1870 unsigned Reg = getVectorListStart();
1871 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1872 OS << Reg + i << " ";
1873 OS << ">";
1874 break;
1875 }
1876 case k_VectorIndex:
1877 OS << "<vectorindex " << getVectorIndex() << ">";
1878 break;
1879 case k_SysReg:
1880 OS << "<sysreg: " << getSysReg() << '>';
1881 break;
1882 case k_Token:
1883 OS << "'" << getToken() << "'";
1884 break;
1885 case k_SysCR:
1886 OS << "c" << getSysCR();
1887 break;
1888 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001889 StringRef Name = getPrefetchName();
1890 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001891 OS << "<prfop " << Name << ">";
1892 else
1893 OS << "<prfop invalid #" << getPrefetch() << ">";
1894 break;
1895 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001896 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001897 OS << getPSBHintName();
1898 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001899 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001900 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1901 << getShiftExtendAmount();
1902 if (!hasShiftExtendAmount())
1903 OS << "<imp>";
1904 OS << '>';
1905 break;
1906 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001907}
1908
1909/// @name Auto-generated Match Functions
1910/// {
1911
1912static unsigned MatchRegisterName(StringRef Name);
1913
1914/// }
1915
1916static unsigned matchVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001917 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001918 .Case("v0", AArch64::Q0)
1919 .Case("v1", AArch64::Q1)
1920 .Case("v2", AArch64::Q2)
1921 .Case("v3", AArch64::Q3)
1922 .Case("v4", AArch64::Q4)
1923 .Case("v5", AArch64::Q5)
1924 .Case("v6", AArch64::Q6)
1925 .Case("v7", AArch64::Q7)
1926 .Case("v8", AArch64::Q8)
1927 .Case("v9", AArch64::Q9)
1928 .Case("v10", AArch64::Q10)
1929 .Case("v11", AArch64::Q11)
1930 .Case("v12", AArch64::Q12)
1931 .Case("v13", AArch64::Q13)
1932 .Case("v14", AArch64::Q14)
1933 .Case("v15", AArch64::Q15)
1934 .Case("v16", AArch64::Q16)
1935 .Case("v17", AArch64::Q17)
1936 .Case("v18", AArch64::Q18)
1937 .Case("v19", AArch64::Q19)
1938 .Case("v20", AArch64::Q20)
1939 .Case("v21", AArch64::Q21)
1940 .Case("v22", AArch64::Q22)
1941 .Case("v23", AArch64::Q23)
1942 .Case("v24", AArch64::Q24)
1943 .Case("v25", AArch64::Q25)
1944 .Case("v26", AArch64::Q26)
1945 .Case("v27", AArch64::Q27)
1946 .Case("v28", AArch64::Q28)
1947 .Case("v29", AArch64::Q29)
1948 .Case("v30", AArch64::Q30)
1949 .Case("v31", AArch64::Q31)
1950 .Default(0);
1951}
1952
1953static bool isValidVectorKind(StringRef Name) {
1954 return StringSwitch<bool>(Name.lower())
1955 .Case(".8b", true)
1956 .Case(".16b", true)
1957 .Case(".4h", true)
1958 .Case(".8h", true)
1959 .Case(".2s", true)
1960 .Case(".4s", true)
1961 .Case(".1d", true)
1962 .Case(".2d", true)
1963 .Case(".1q", true)
1964 // Accept the width neutral ones, too, for verbose syntax. If those
1965 // aren't used in the right places, the token operand won't match so
1966 // all will work out.
1967 .Case(".b", true)
1968 .Case(".h", true)
1969 .Case(".s", true)
1970 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001971 // Needed for fp16 scalar pairwise reductions
1972 .Case(".2h", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001973 .Default(false);
1974}
1975
1976static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1977 char &ElementKind) {
1978 assert(isValidVectorKind(Name));
1979
1980 ElementKind = Name.lower()[Name.size() - 1];
1981 NumElements = 0;
1982
1983 if (Name.size() == 2)
1984 return;
1985
1986 // Parse the lane count
1987 Name = Name.drop_front();
1988 while (isdigit(Name.front())) {
1989 NumElements = 10 * NumElements + (Name.front() - '0');
1990 Name = Name.drop_front();
1991 }
1992}
1993
1994bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1995 SMLoc &EndLoc) {
1996 StartLoc = getLoc();
1997 RegNo = tryParseRegister();
1998 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1999 return (RegNo == (unsigned)-1);
2000}
2001
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002002// Matches a register name or register alias previously defined by '.req'
2003unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
2004 bool isVector) {
2005 unsigned RegNum = isVector ? matchVectorRegName(Name)
2006 : MatchRegisterName(Name);
2007
2008 if (RegNum == 0) {
2009 // Check for aliases registered via .req. Canonicalize to lower case.
2010 // That's more consistent since register names are case insensitive, and
2011 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2012 auto Entry = RegisterReqs.find(Name.lower());
2013 if (Entry == RegisterReqs.end())
2014 return 0;
2015 // set RegNum if the match is the right kind of register
2016 if (isVector == Entry->getValue().first)
2017 RegNum = Entry->getValue().second;
2018 }
2019 return RegNum;
2020}
2021
Tim Northover3b0846e2014-05-24 12:50:23 +00002022/// tryParseRegister - Try to parse a register name. The token must be an
2023/// Identifier when called, and if it is a register name the token is eaten and
2024/// the register is added to the operand list.
2025int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002026 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002027 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002028 if (Tok.isNot(AsmToken::Identifier))
2029 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002030
2031 std::string lowerCase = Tok.getString().lower();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002032 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
Tim Northover3b0846e2014-05-24 12:50:23 +00002033 // Also handle a few aliases of registers.
2034 if (RegNum == 0)
2035 RegNum = StringSwitch<unsigned>(lowerCase)
2036 .Case("fp", AArch64::FP)
2037 .Case("lr", AArch64::LR)
2038 .Case("x31", AArch64::XZR)
2039 .Case("w31", AArch64::WZR)
2040 .Default(0);
2041
2042 if (RegNum == 0)
2043 return -1;
2044
2045 Parser.Lex(); // Eat identifier token.
2046 return RegNum;
2047}
2048
2049/// tryMatchVectorRegister - Try to parse a vector register name with optional
2050/// kind specifier. If it is a register specifier, eat the token and return it.
2051int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002052 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002053 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2054 TokError("vector register expected");
2055 return -1;
2056 }
2057
2058 StringRef Name = Parser.getTok().getString();
2059 // If there is a kind specifier, it's separated from the register name by
2060 // a '.'.
2061 size_t Start = 0, Next = Name.find('.');
2062 StringRef Head = Name.slice(Start, Next);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002063 unsigned RegNum = matchRegisterNameAlias(Head, true);
2064
Tim Northover3b0846e2014-05-24 12:50:23 +00002065 if (RegNum) {
2066 if (Next != StringRef::npos) {
2067 Kind = Name.slice(Next, StringRef::npos);
2068 if (!isValidVectorKind(Kind)) {
2069 TokError("invalid vector kind qualifier");
2070 return -1;
2071 }
2072 }
2073 Parser.Lex(); // Eat the register token.
2074 return RegNum;
2075 }
2076
2077 if (expected)
2078 TokError("vector register expected");
2079 return -1;
2080}
2081
2082/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002083OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002084AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002085 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002086 SMLoc S = getLoc();
2087
2088 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2089 Error(S, "Expected cN operand where 0 <= N <= 15");
2090 return MatchOperand_ParseFail;
2091 }
2092
2093 StringRef Tok = Parser.getTok().getIdentifier();
2094 if (Tok[0] != 'c' && Tok[0] != 'C') {
2095 Error(S, "Expected cN operand where 0 <= N <= 15");
2096 return MatchOperand_ParseFail;
2097 }
2098
2099 uint32_t CRNum;
2100 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2101 if (BadNum || CRNum > 15) {
2102 Error(S, "Expected cN operand where 0 <= N <= 15");
2103 return MatchOperand_ParseFail;
2104 }
2105
2106 Parser.Lex(); // Eat identifier token.
2107 Operands.push_back(
2108 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2109 return MatchOperand_Success;
2110}
2111
2112/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002113OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002114AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002115 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002116 SMLoc S = getLoc();
2117 const AsmToken &Tok = Parser.getTok();
2118 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002119 // Eat optional hash.
2120 if (parseOptionalToken(AsmToken::Hash) ||
2121 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002122 const MCExpr *ImmVal;
2123 if (getParser().parseExpression(ImmVal))
2124 return MatchOperand_ParseFail;
2125
2126 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2127 if (!MCE) {
2128 TokError("immediate value expected for prefetch operand");
2129 return MatchOperand_ParseFail;
2130 }
2131 unsigned prfop = MCE->getValue();
2132 if (prfop > 31) {
2133 TokError("prefetch operand out of range, [0,31] expected");
2134 return MatchOperand_ParseFail;
2135 }
2136
Tim Northovere6ae6762016-07-05 21:23:04 +00002137 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2138 Operands.push_back(AArch64Operand::CreatePrefetch(
2139 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002140 return MatchOperand_Success;
2141 }
2142
2143 if (Tok.isNot(AsmToken::Identifier)) {
2144 TokError("pre-fetch hint expected");
2145 return MatchOperand_ParseFail;
2146 }
2147
Tim Northovere6ae6762016-07-05 21:23:04 +00002148 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2149 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002150 TokError("pre-fetch hint expected");
2151 return MatchOperand_ParseFail;
2152 }
2153
2154 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002155 Operands.push_back(AArch64Operand::CreatePrefetch(
2156 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002157 return MatchOperand_Success;
2158}
2159
Oliver Stannarda34e4702015-12-01 10:48:51 +00002160/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002161OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002162AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2163 MCAsmParser &Parser = getParser();
2164 SMLoc S = getLoc();
2165 const AsmToken &Tok = Parser.getTok();
2166 if (Tok.isNot(AsmToken::Identifier)) {
2167 TokError("invalid operand for instruction");
2168 return MatchOperand_ParseFail;
2169 }
2170
Tim Northovere6ae6762016-07-05 21:23:04 +00002171 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2172 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002173 TokError("invalid operand for instruction");
2174 return MatchOperand_ParseFail;
2175 }
2176
2177 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002178 Operands.push_back(AArch64Operand::CreatePSBHint(
2179 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002180 return MatchOperand_Success;
2181}
2182
Tim Northover3b0846e2014-05-24 12:50:23 +00002183/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2184/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002185OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002186AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002187 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002188 SMLoc S = getLoc();
2189 const MCExpr *Expr;
2190
2191 if (Parser.getTok().is(AsmToken::Hash)) {
2192 Parser.Lex(); // Eat hash token.
2193 }
2194
2195 if (parseSymbolicImmVal(Expr))
2196 return MatchOperand_ParseFail;
2197
2198 AArch64MCExpr::VariantKind ELFRefKind;
2199 MCSymbolRefExpr::VariantKind DarwinRefKind;
2200 int64_t Addend;
2201 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2202 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2203 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2204 // No modifier was specified at all; this is the syntax for an ELF basic
2205 // ADRP relocation (unfortunately).
2206 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002207 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002208 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2209 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2210 Addend != 0) {
2211 Error(S, "gotpage label reference not allowed an addend");
2212 return MatchOperand_ParseFail;
2213 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2214 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2215 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2216 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2217 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2218 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2219 // The operand must be an @page or @gotpage qualified symbolref.
2220 Error(S, "page or gotpage label reference expected");
2221 return MatchOperand_ParseFail;
2222 }
2223 }
2224
2225 // We have either a label reference possibly with addend or an immediate. The
2226 // addend is a raw value here. The linker will adjust it to only reference the
2227 // page.
2228 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2229 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2230
2231 return MatchOperand_Success;
2232}
2233
2234/// tryParseAdrLabel - Parse and validate a source label for the ADR
2235/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002236OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002237AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2238 SMLoc S = getLoc();
2239 const MCExpr *Expr;
2240
Nirav Davee833c6c2016-11-08 18:31:04 +00002241 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002242 if (getParser().parseExpression(Expr))
2243 return MatchOperand_ParseFail;
2244
2245 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2246 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2247
2248 return MatchOperand_Success;
2249}
2250
2251/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002252OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002253AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002254 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002255 SMLoc S = getLoc();
2256
Nirav Davee833c6c2016-11-08 18:31:04 +00002257 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002258
2259 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002260 bool isNegative = parseOptionalToken(AsmToken::Minus);
2261
Tim Northover3b0846e2014-05-24 12:50:23 +00002262 const AsmToken &Tok = Parser.getTok();
2263 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002264 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002265 if (isNegative)
2266 RealVal.changeSign();
2267
Tim Northover3b0846e2014-05-24 12:50:23 +00002268 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002269 int Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2270 Parser.Lex(); // Eat the token.
2271 // Check for out of range values. As an exception, we let Zero through,
2272 // as we handle that special case in post-processing before matching in
2273 // order to use the zero register for it.
Tim Northover5b44f1ba2015-04-07 22:49:47 +00002274 if (Val == -1 && !RealVal.isPosZero()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002275 TokError("expected compatible register or floating-point constant");
2276 return MatchOperand_ParseFail;
2277 }
2278 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2279 return MatchOperand_Success;
2280 }
2281 if (Tok.is(AsmToken::Integer)) {
2282 int64_t Val;
2283 if (!isNegative && Tok.getString().startswith("0x")) {
2284 Val = Tok.getIntVal();
2285 if (Val > 255 || Val < 0) {
2286 TokError("encoded floating point value out of range");
2287 return MatchOperand_ParseFail;
2288 }
2289 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002290 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002291 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2292 // If we had a '-' in front, toggle the sign bit.
2293 IntVal ^= (uint64_t)isNegative << 63;
2294 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2295 }
2296 Parser.Lex(); // Eat the token.
2297 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2298 return MatchOperand_Success;
2299 }
2300
2301 if (!Hash)
2302 return MatchOperand_NoMatch;
2303
2304 TokError("invalid floating point immediate");
2305 return MatchOperand_ParseFail;
2306}
2307
2308/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002309OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002310AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002311 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002312 SMLoc S = getLoc();
2313
2314 if (Parser.getTok().is(AsmToken::Hash))
2315 Parser.Lex(); // Eat '#'
2316 else if (Parser.getTok().isNot(AsmToken::Integer))
2317 // Operand should start from # or should be integer, emit error otherwise.
2318 return MatchOperand_NoMatch;
2319
2320 const MCExpr *Imm;
2321 if (parseSymbolicImmVal(Imm))
2322 return MatchOperand_ParseFail;
2323 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2324 uint64_t ShiftAmount = 0;
2325 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2326 if (MCE) {
2327 int64_t Val = MCE->getValue();
2328 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002329 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002330 ShiftAmount = 12;
2331 }
2332 }
2333 SMLoc E = Parser.getTok().getLoc();
2334 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2335 getContext()));
2336 return MatchOperand_Success;
2337 }
2338
2339 // Eat ','
2340 Parser.Lex();
2341
2342 // The optional operand must be "lsl #N" where N is non-negative.
2343 if (!Parser.getTok().is(AsmToken::Identifier) ||
2344 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2345 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2346 return MatchOperand_ParseFail;
2347 }
2348
2349 // Eat 'lsl'
2350 Parser.Lex();
2351
Nirav Davee833c6c2016-11-08 18:31:04 +00002352 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002353
2354 if (Parser.getTok().isNot(AsmToken::Integer)) {
2355 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2356 return MatchOperand_ParseFail;
2357 }
2358
2359 int64_t ShiftAmount = Parser.getTok().getIntVal();
2360
2361 if (ShiftAmount < 0) {
2362 Error(Parser.getTok().getLoc(), "positive shift amount required");
2363 return MatchOperand_ParseFail;
2364 }
2365 Parser.Lex(); // Eat the number
2366
2367 SMLoc E = Parser.getTok().getLoc();
2368 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2369 S, E, getContext()));
2370 return MatchOperand_Success;
2371}
2372
2373/// parseCondCodeString - Parse a Condition Code string.
2374AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2375 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2376 .Case("eq", AArch64CC::EQ)
2377 .Case("ne", AArch64CC::NE)
2378 .Case("cs", AArch64CC::HS)
2379 .Case("hs", AArch64CC::HS)
2380 .Case("cc", AArch64CC::LO)
2381 .Case("lo", AArch64CC::LO)
2382 .Case("mi", AArch64CC::MI)
2383 .Case("pl", AArch64CC::PL)
2384 .Case("vs", AArch64CC::VS)
2385 .Case("vc", AArch64CC::VC)
2386 .Case("hi", AArch64CC::HI)
2387 .Case("ls", AArch64CC::LS)
2388 .Case("ge", AArch64CC::GE)
2389 .Case("lt", AArch64CC::LT)
2390 .Case("gt", AArch64CC::GT)
2391 .Case("le", AArch64CC::LE)
2392 .Case("al", AArch64CC::AL)
2393 .Case("nv", AArch64CC::NV)
2394 .Default(AArch64CC::Invalid);
2395 return CC;
2396}
2397
2398/// parseCondCode - Parse a Condition Code operand.
2399bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2400 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002401 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002402 SMLoc S = getLoc();
2403 const AsmToken &Tok = Parser.getTok();
2404 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2405
2406 StringRef Cond = Tok.getString();
2407 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2408 if (CC == AArch64CC::Invalid)
2409 return TokError("invalid condition code");
2410 Parser.Lex(); // Eat identifier token.
2411
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002412 if (invertCondCode) {
2413 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2414 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002415 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002416 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002417
2418 Operands.push_back(
2419 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2420 return false;
2421}
2422
2423/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2424/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002425OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002426AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002427 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002428 const AsmToken &Tok = Parser.getTok();
2429 std::string LowerID = Tok.getString().lower();
2430 AArch64_AM::ShiftExtendType ShOp =
2431 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2432 .Case("lsl", AArch64_AM::LSL)
2433 .Case("lsr", AArch64_AM::LSR)
2434 .Case("asr", AArch64_AM::ASR)
2435 .Case("ror", AArch64_AM::ROR)
2436 .Case("msl", AArch64_AM::MSL)
2437 .Case("uxtb", AArch64_AM::UXTB)
2438 .Case("uxth", AArch64_AM::UXTH)
2439 .Case("uxtw", AArch64_AM::UXTW)
2440 .Case("uxtx", AArch64_AM::UXTX)
2441 .Case("sxtb", AArch64_AM::SXTB)
2442 .Case("sxth", AArch64_AM::SXTH)
2443 .Case("sxtw", AArch64_AM::SXTW)
2444 .Case("sxtx", AArch64_AM::SXTX)
2445 .Default(AArch64_AM::InvalidShiftExtend);
2446
2447 if (ShOp == AArch64_AM::InvalidShiftExtend)
2448 return MatchOperand_NoMatch;
2449
2450 SMLoc S = Tok.getLoc();
2451 Parser.Lex();
2452
Nirav Davee833c6c2016-11-08 18:31:04 +00002453 bool Hash = parseOptionalToken(AsmToken::Hash);
2454
Tim Northover3b0846e2014-05-24 12:50:23 +00002455 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2456 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2457 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2458 ShOp == AArch64_AM::MSL) {
2459 // We expect a number here.
2460 TokError("expected #imm after shift specifier");
2461 return MatchOperand_ParseFail;
2462 }
2463
Chad Rosier2ff37b82016-12-27 16:58:09 +00002464 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002465 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2466 Operands.push_back(
2467 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2468 return MatchOperand_Success;
2469 }
2470
Chad Rosier2ff37b82016-12-27 16:58:09 +00002471 // Make sure we do actually have a number, identifier or a parenthesized
2472 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002473 SMLoc E = Parser.getTok().getLoc();
2474 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002475 !Parser.getTok().is(AsmToken::LParen) &&
2476 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002477 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002478 return MatchOperand_ParseFail;
2479 }
2480
2481 const MCExpr *ImmVal;
2482 if (getParser().parseExpression(ImmVal))
2483 return MatchOperand_ParseFail;
2484
2485 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2486 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002487 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002488 return MatchOperand_ParseFail;
2489 }
2490
Jim Grosbach57fd2622014-09-23 22:16:02 +00002491 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002492 Operands.push_back(AArch64Operand::CreateShiftExtend(
2493 ShOp, MCE->getValue(), true, S, E, getContext()));
2494 return MatchOperand_Success;
2495}
2496
2497/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2498/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2499bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2500 OperandVector &Operands) {
2501 if (Name.find('.') != StringRef::npos)
2502 return TokError("invalid operand");
2503
2504 Mnemonic = Name;
2505 Operands.push_back(
2506 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2507
Rafael Espindola961d4692014-11-11 05:18:41 +00002508 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002509 const AsmToken &Tok = Parser.getTok();
2510 StringRef Op = Tok.getString();
2511 SMLoc S = Tok.getLoc();
2512
2513 const MCExpr *Expr = nullptr;
2514
2515#define SYS_ALIAS(op1, Cn, Cm, op2) \
2516 do { \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002517 Expr = MCConstantExpr::create(op1, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002518 Operands.push_back( \
2519 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
2520 Operands.push_back( \
2521 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext())); \
2522 Operands.push_back( \
2523 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext())); \
Jim Grosbach13760bd2015-05-30 01:25:56 +00002524 Expr = MCConstantExpr::create(op2, getContext()); \
Tim Northover3b0846e2014-05-24 12:50:23 +00002525 Operands.push_back( \
2526 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \
Eugene Zelenko049b0172017-01-06 00:30:53 +00002527 } while (false)
Tim Northover3b0846e2014-05-24 12:50:23 +00002528
2529 if (Mnemonic == "ic") {
2530 if (!Op.compare_lower("ialluis")) {
2531 // SYS #0, C7, C1, #0
2532 SYS_ALIAS(0, 7, 1, 0);
2533 } else if (!Op.compare_lower("iallu")) {
2534 // SYS #0, C7, C5, #0
2535 SYS_ALIAS(0, 7, 5, 0);
2536 } else if (!Op.compare_lower("ivau")) {
2537 // SYS #3, C7, C5, #1
2538 SYS_ALIAS(3, 7, 5, 1);
2539 } else {
2540 return TokError("invalid operand for IC instruction");
2541 }
2542 } else if (Mnemonic == "dc") {
2543 if (!Op.compare_lower("zva")) {
2544 // SYS #3, C7, C4, #1
2545 SYS_ALIAS(3, 7, 4, 1);
2546 } else if (!Op.compare_lower("ivac")) {
2547 // SYS #3, C7, C6, #1
2548 SYS_ALIAS(0, 7, 6, 1);
2549 } else if (!Op.compare_lower("isw")) {
2550 // SYS #0, C7, C6, #2
2551 SYS_ALIAS(0, 7, 6, 2);
2552 } else if (!Op.compare_lower("cvac")) {
2553 // SYS #3, C7, C10, #1
2554 SYS_ALIAS(3, 7, 10, 1);
2555 } else if (!Op.compare_lower("csw")) {
2556 // SYS #0, C7, C10, #2
2557 SYS_ALIAS(0, 7, 10, 2);
2558 } else if (!Op.compare_lower("cvau")) {
2559 // SYS #3, C7, C11, #1
2560 SYS_ALIAS(3, 7, 11, 1);
2561 } else if (!Op.compare_lower("civac")) {
2562 // SYS #3, C7, C14, #1
2563 SYS_ALIAS(3, 7, 14, 1);
2564 } else if (!Op.compare_lower("cisw")) {
2565 // SYS #0, C7, C14, #2
2566 SYS_ALIAS(0, 7, 14, 2);
Oliver Stannard1a81cc9f2015-11-26 15:28:47 +00002567 } else if (!Op.compare_lower("cvap")) {
2568 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2569 // SYS #3, C7, C12, #1
2570 SYS_ALIAS(3, 7, 12, 1);
2571 } else {
2572 return TokError("DC CVAP requires ARMv8.2a");
2573 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002574 } else {
2575 return TokError("invalid operand for DC instruction");
2576 }
2577 } else if (Mnemonic == "at") {
2578 if (!Op.compare_lower("s1e1r")) {
2579 // SYS #0, C7, C8, #0
2580 SYS_ALIAS(0, 7, 8, 0);
2581 } else if (!Op.compare_lower("s1e2r")) {
2582 // SYS #4, C7, C8, #0
2583 SYS_ALIAS(4, 7, 8, 0);
2584 } else if (!Op.compare_lower("s1e3r")) {
2585 // SYS #6, C7, C8, #0
2586 SYS_ALIAS(6, 7, 8, 0);
2587 } else if (!Op.compare_lower("s1e1w")) {
2588 // SYS #0, C7, C8, #1
2589 SYS_ALIAS(0, 7, 8, 1);
2590 } else if (!Op.compare_lower("s1e2w")) {
2591 // SYS #4, C7, C8, #1
2592 SYS_ALIAS(4, 7, 8, 1);
2593 } else if (!Op.compare_lower("s1e3w")) {
2594 // SYS #6, C7, C8, #1
2595 SYS_ALIAS(6, 7, 8, 1);
2596 } else if (!Op.compare_lower("s1e0r")) {
2597 // SYS #0, C7, C8, #3
2598 SYS_ALIAS(0, 7, 8, 2);
2599 } else if (!Op.compare_lower("s1e0w")) {
2600 // SYS #0, C7, C8, #3
2601 SYS_ALIAS(0, 7, 8, 3);
2602 } else if (!Op.compare_lower("s12e1r")) {
2603 // SYS #4, C7, C8, #4
2604 SYS_ALIAS(4, 7, 8, 4);
2605 } else if (!Op.compare_lower("s12e1w")) {
2606 // SYS #4, C7, C8, #5
2607 SYS_ALIAS(4, 7, 8, 5);
2608 } else if (!Op.compare_lower("s12e0r")) {
2609 // SYS #4, C7, C8, #6
2610 SYS_ALIAS(4, 7, 8, 6);
2611 } else if (!Op.compare_lower("s12e0w")) {
2612 // SYS #4, C7, C8, #7
2613 SYS_ALIAS(4, 7, 8, 7);
Oliver Stannard64c167d2015-11-26 15:34:44 +00002614 } else if (!Op.compare_lower("s1e1rp")) {
2615 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2616 // SYS #0, C7, C9, #0
2617 SYS_ALIAS(0, 7, 9, 0);
2618 } else {
2619 return TokError("AT S1E1RP requires ARMv8.2a");
2620 }
2621 } else if (!Op.compare_lower("s1e1wp")) {
2622 if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2623 // SYS #0, C7, C9, #1
2624 SYS_ALIAS(0, 7, 9, 1);
2625 } else {
2626 return TokError("AT S1E1WP requires ARMv8.2a");
2627 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002628 } else {
2629 return TokError("invalid operand for AT instruction");
2630 }
2631 } else if (Mnemonic == "tlbi") {
2632 if (!Op.compare_lower("vmalle1is")) {
2633 // SYS #0, C8, C3, #0
2634 SYS_ALIAS(0, 8, 3, 0);
2635 } else if (!Op.compare_lower("alle2is")) {
2636 // SYS #4, C8, C3, #0
2637 SYS_ALIAS(4, 8, 3, 0);
2638 } else if (!Op.compare_lower("alle3is")) {
2639 // SYS #6, C8, C3, #0
2640 SYS_ALIAS(6, 8, 3, 0);
2641 } else if (!Op.compare_lower("vae1is")) {
2642 // SYS #0, C8, C3, #1
2643 SYS_ALIAS(0, 8, 3, 1);
2644 } else if (!Op.compare_lower("vae2is")) {
2645 // SYS #4, C8, C3, #1
2646 SYS_ALIAS(4, 8, 3, 1);
2647 } else if (!Op.compare_lower("vae3is")) {
2648 // SYS #6, C8, C3, #1
2649 SYS_ALIAS(6, 8, 3, 1);
2650 } else if (!Op.compare_lower("aside1is")) {
2651 // SYS #0, C8, C3, #2
2652 SYS_ALIAS(0, 8, 3, 2);
2653 } else if (!Op.compare_lower("vaae1is")) {
2654 // SYS #0, C8, C3, #3
2655 SYS_ALIAS(0, 8, 3, 3);
2656 } else if (!Op.compare_lower("alle1is")) {
2657 // SYS #4, C8, C3, #4
2658 SYS_ALIAS(4, 8, 3, 4);
2659 } else if (!Op.compare_lower("vale1is")) {
2660 // SYS #0, C8, C3, #5
2661 SYS_ALIAS(0, 8, 3, 5);
2662 } else if (!Op.compare_lower("vaale1is")) {
2663 // SYS #0, C8, C3, #7
2664 SYS_ALIAS(0, 8, 3, 7);
2665 } else if (!Op.compare_lower("vmalle1")) {
2666 // SYS #0, C8, C7, #0
2667 SYS_ALIAS(0, 8, 7, 0);
2668 } else if (!Op.compare_lower("alle2")) {
2669 // SYS #4, C8, C7, #0
2670 SYS_ALIAS(4, 8, 7, 0);
2671 } else if (!Op.compare_lower("vale2is")) {
2672 // SYS #4, C8, C3, #5
2673 SYS_ALIAS(4, 8, 3, 5);
2674 } else if (!Op.compare_lower("vale3is")) {
2675 // SYS #6, C8, C3, #5
2676 SYS_ALIAS(6, 8, 3, 5);
2677 } else if (!Op.compare_lower("alle3")) {
2678 // SYS #6, C8, C7, #0
2679 SYS_ALIAS(6, 8, 7, 0);
2680 } else if (!Op.compare_lower("vae1")) {
2681 // SYS #0, C8, C7, #1
2682 SYS_ALIAS(0, 8, 7, 1);
2683 } else if (!Op.compare_lower("vae2")) {
2684 // SYS #4, C8, C7, #1
2685 SYS_ALIAS(4, 8, 7, 1);
2686 } else if (!Op.compare_lower("vae3")) {
2687 // SYS #6, C8, C7, #1
2688 SYS_ALIAS(6, 8, 7, 1);
2689 } else if (!Op.compare_lower("aside1")) {
2690 // SYS #0, C8, C7, #2
2691 SYS_ALIAS(0, 8, 7, 2);
2692 } else if (!Op.compare_lower("vaae1")) {
2693 // SYS #0, C8, C7, #3
2694 SYS_ALIAS(0, 8, 7, 3);
2695 } else if (!Op.compare_lower("alle1")) {
2696 // SYS #4, C8, C7, #4
2697 SYS_ALIAS(4, 8, 7, 4);
2698 } else if (!Op.compare_lower("vale1")) {
2699 // SYS #0, C8, C7, #5
2700 SYS_ALIAS(0, 8, 7, 5);
2701 } else if (!Op.compare_lower("vale2")) {
2702 // SYS #4, C8, C7, #5
2703 SYS_ALIAS(4, 8, 7, 5);
2704 } else if (!Op.compare_lower("vale3")) {
2705 // SYS #6, C8, C7, #5
2706 SYS_ALIAS(6, 8, 7, 5);
2707 } else if (!Op.compare_lower("vaale1")) {
2708 // SYS #0, C8, C7, #7
2709 SYS_ALIAS(0, 8, 7, 7);
2710 } else if (!Op.compare_lower("ipas2e1")) {
2711 // SYS #4, C8, C4, #1
2712 SYS_ALIAS(4, 8, 4, 1);
2713 } else if (!Op.compare_lower("ipas2le1")) {
2714 // SYS #4, C8, C4, #5
2715 SYS_ALIAS(4, 8, 4, 5);
2716 } else if (!Op.compare_lower("ipas2e1is")) {
2717 // SYS #4, C8, C4, #1
2718 SYS_ALIAS(4, 8, 0, 1);
2719 } else if (!Op.compare_lower("ipas2le1is")) {
2720 // SYS #4, C8, C4, #5
2721 SYS_ALIAS(4, 8, 0, 5);
2722 } else if (!Op.compare_lower("vmalls12e1")) {
2723 // SYS #4, C8, C7, #6
2724 SYS_ALIAS(4, 8, 7, 6);
2725 } else if (!Op.compare_lower("vmalls12e1is")) {
2726 // SYS #4, C8, C3, #6
2727 SYS_ALIAS(4, 8, 3, 6);
2728 } else {
2729 return TokError("invalid operand for TLBI instruction");
2730 }
2731 }
2732
2733#undef SYS_ALIAS
2734
2735 Parser.Lex(); // Eat operand.
2736
2737 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2738 bool HasRegister = false;
2739
2740 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002741 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002742 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2743 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002744 HasRegister = true;
2745 }
2746
Tim Northover3b0846e2014-05-24 12:50:23 +00002747 if (ExpectRegister && !HasRegister) {
2748 return TokError("specified " + Mnemonic + " op requires a register");
2749 }
2750 else if (!ExpectRegister && HasRegister) {
2751 return TokError("specified " + Mnemonic + " op does not use a register");
2752 }
2753
Nirav Davee833c6c2016-11-08 18:31:04 +00002754 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2755 return true;
2756
Tim Northover3b0846e2014-05-24 12:50:23 +00002757 return false;
2758}
2759
Alex Bradbury58eba092016-11-01 16:32:05 +00002760OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002761AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002762 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002763 const AsmToken &Tok = Parser.getTok();
2764
2765 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002766 if (parseOptionalToken(AsmToken::Hash) ||
2767 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002768 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002769 const MCExpr *ImmVal;
2770 SMLoc ExprLoc = getLoc();
2771 if (getParser().parseExpression(ImmVal))
2772 return MatchOperand_ParseFail;
2773 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2774 if (!MCE) {
2775 Error(ExprLoc, "immediate value expected for barrier operand");
2776 return MatchOperand_ParseFail;
2777 }
2778 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2779 Error(ExprLoc, "barrier operand out of range");
2780 return MatchOperand_ParseFail;
2781 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002782 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2783 Operands.push_back(AArch64Operand::CreateBarrier(
2784 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002785 return MatchOperand_Success;
2786 }
2787
2788 if (Tok.isNot(AsmToken::Identifier)) {
2789 TokError("invalid operand for instruction");
2790 return MatchOperand_ParseFail;
2791 }
2792
Tim Northovere6ae6762016-07-05 21:23:04 +00002793 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2794 if (!DB) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002795 TokError("invalid barrier option name");
2796 return MatchOperand_ParseFail;
2797 }
2798
2799 // The only valid named option for ISB is 'sy'
Tim Northovere6ae6762016-07-05 21:23:04 +00002800 if (Mnemonic == "isb" && DB->Encoding != AArch64DB::sy) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002801 TokError("'sy' or #imm operand expected");
2802 return MatchOperand_ParseFail;
2803 }
2804
Tim Northovere6ae6762016-07-05 21:23:04 +00002805 Operands.push_back(AArch64Operand::CreateBarrier(
2806 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002807 Parser.Lex(); // Consume the option
2808
2809 return MatchOperand_Success;
2810}
2811
Alex Bradbury58eba092016-11-01 16:32:05 +00002812OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002813AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002814 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002815 const AsmToken &Tok = Parser.getTok();
2816
2817 if (Tok.isNot(AsmToken::Identifier))
2818 return MatchOperand_NoMatch;
2819
Tim Northovere6ae6762016-07-05 21:23:04 +00002820 int MRSReg, MSRReg;
2821 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2822 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2823 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2824 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2825 } else
2826 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002827
Tim Northovere6ae6762016-07-05 21:23:04 +00002828 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2829 unsigned PStateImm = -1;
2830 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2831 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002832
Tim Northovere6ae6762016-07-05 21:23:04 +00002833 Operands.push_back(
2834 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2835 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002836 Parser.Lex(); // Eat identifier
2837
2838 return MatchOperand_Success;
2839}
2840
2841/// tryParseVectorRegister - Parse a vector register operand.
2842bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002843 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002844 if (Parser.getTok().isNot(AsmToken::Identifier))
2845 return true;
2846
2847 SMLoc S = getLoc();
2848 // Check for a vector register specifier first.
2849 StringRef Kind;
2850 int64_t Reg = tryMatchVectorRegister(Kind, false);
2851 if (Reg == -1)
2852 return true;
2853 Operands.push_back(
2854 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2855 // If there was an explicit qualifier, that goes on as a literal text
2856 // operand.
2857 if (!Kind.empty())
2858 Operands.push_back(
2859 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2860
2861 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002862 SMLoc SIdx = getLoc();
2863 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002864 const MCExpr *ImmVal;
2865 if (getParser().parseExpression(ImmVal))
2866 return false;
2867 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2868 if (!MCE) {
2869 TokError("immediate value expected for vector index");
2870 return false;
2871 }
2872
2873 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002874
Nirav Davee833c6c2016-11-08 18:31:04 +00002875 if (parseToken(AsmToken::RBrac, "']' expected"))
2876 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002877
2878 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2879 E, getContext()));
2880 }
2881
2882 return false;
2883}
2884
2885/// parseRegister - Parse a non-vector register operand.
2886bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002887 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002888 SMLoc S = getLoc();
2889 // Try for a vector register.
2890 if (!tryParseVectorRegister(Operands))
2891 return false;
2892
2893 // Try for a scalar register.
2894 int64_t Reg = tryParseRegister();
2895 if (Reg == -1)
2896 return true;
2897 Operands.push_back(
2898 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2899
2900 // A small number of instructions (FMOVXDhighr, for example) have "[1]"
2901 // as a string token in the instruction itself.
Nirav Davee833c6c2016-11-08 18:31:04 +00002902 SMLoc LBracS = getLoc();
2903 const AsmToken &Tok = Parser.getTok();
2904 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002905 if (Tok.is(AsmToken::Integer)) {
2906 SMLoc IntS = getLoc();
2907 int64_t Val = Tok.getIntVal();
2908 if (Val == 1) {
2909 Parser.Lex();
Nirav Davee833c6c2016-11-08 18:31:04 +00002910 SMLoc RBracS = getLoc();
2911 if (parseOptionalToken(AsmToken::RBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002912 Operands.push_back(
2913 AArch64Operand::CreateToken("[", false, LBracS, getContext()));
2914 Operands.push_back(
2915 AArch64Operand::CreateToken("1", false, IntS, getContext()));
2916 Operands.push_back(
2917 AArch64Operand::CreateToken("]", false, RBracS, getContext()));
2918 return false;
2919 }
2920 }
2921 }
2922 }
2923
2924 return false;
2925}
2926
2927bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002928 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002929 bool HasELFModifier = false;
2930 AArch64MCExpr::VariantKind RefKind;
2931
Nirav Davee833c6c2016-11-08 18:31:04 +00002932 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002933 HasELFModifier = true;
2934
Nirav Davee833c6c2016-11-08 18:31:04 +00002935 if (Parser.getTok().isNot(AsmToken::Identifier))
2936 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002937
2938 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2939 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2940 .Case("lo12", AArch64MCExpr::VK_LO12)
2941 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2942 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2943 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2944 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2945 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2946 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2947 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2948 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2949 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2950 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2951 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2952 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2953 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2954 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2955 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2956 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2957 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2958 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2959 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2960 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2961 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2962 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2963 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2964 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2965 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2966 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2967 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2968 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2969 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2970 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2971 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2972 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2973 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2974 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2975 .Default(AArch64MCExpr::VK_INVALID);
2976
Nirav Davee833c6c2016-11-08 18:31:04 +00002977 if (RefKind == AArch64MCExpr::VK_INVALID)
2978 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002979
2980 Parser.Lex(); // Eat identifier
2981
Nirav Davee833c6c2016-11-08 18:31:04 +00002982 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002983 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002984 }
2985
2986 if (getParser().parseExpression(ImmVal))
2987 return true;
2988
2989 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002990 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002991
2992 return false;
2993}
2994
2995/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2996bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002997 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002998 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2999 SMLoc S = getLoc();
3000 Parser.Lex(); // Eat left bracket token.
3001 StringRef Kind;
3002 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
3003 if (FirstReg == -1)
3004 return true;
3005 int64_t PrevReg = FirstReg;
3006 unsigned Count = 1;
3007
Nirav Davee833c6c2016-11-08 18:31:04 +00003008 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003009 SMLoc Loc = getLoc();
3010 StringRef NextKind;
3011 int64_t Reg = tryMatchVectorRegister(NextKind, true);
3012 if (Reg == -1)
3013 return true;
3014 // Any Kind suffices must match on all regs in the list.
3015 if (Kind != NextKind)
3016 return Error(Loc, "mismatched register size suffix");
3017
3018 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3019
3020 if (Space == 0 || Space > 3) {
3021 return Error(Loc, "invalid number of vectors");
3022 }
3023
3024 Count += Space;
3025 }
3026 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003027 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003028 SMLoc Loc = getLoc();
3029 StringRef NextKind;
3030 int64_t Reg = tryMatchVectorRegister(NextKind, true);
3031 if (Reg == -1)
3032 return true;
3033 // Any Kind suffices must match on all regs in the list.
3034 if (Kind != NextKind)
3035 return Error(Loc, "mismatched register size suffix");
3036
3037 // Registers must be incremental (with wraparound at 31)
3038 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
3039 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
3040 return Error(Loc, "registers must be sequential");
3041
3042 PrevReg = Reg;
3043 ++Count;
3044 }
3045 }
3046
Nirav Davee833c6c2016-11-08 18:31:04 +00003047 if (parseToken(AsmToken::RCurly, "'}' expected"))
3048 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003049
3050 if (Count > 4)
3051 return Error(S, "invalid number of vectors");
3052
3053 unsigned NumElements = 0;
3054 char ElementKind = 0;
3055 if (!Kind.empty())
3056 parseValidVectorKind(Kind, NumElements, ElementKind);
3057
3058 Operands.push_back(AArch64Operand::CreateVectorList(
3059 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
3060
3061 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00003062 SMLoc SIdx = getLoc();
3063 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00003064 const MCExpr *ImmVal;
3065 if (getParser().parseExpression(ImmVal))
3066 return false;
3067 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3068 if (!MCE) {
3069 TokError("immediate value expected for vector index");
3070 return false;
3071 }
3072
3073 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003074 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003075 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003076
3077 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3078 E, getContext()));
3079 }
3080 return false;
3081}
3082
Alex Bradbury58eba092016-11-01 16:32:05 +00003083OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003084AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003085 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003086 const AsmToken &Tok = Parser.getTok();
3087 if (!Tok.is(AsmToken::Identifier))
3088 return MatchOperand_NoMatch;
3089
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003090 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00003091
3092 MCContext &Ctx = getContext();
3093 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3094 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3095 return MatchOperand_NoMatch;
3096
3097 SMLoc S = getLoc();
3098 Parser.Lex(); // Eat register
3099
Nirav Davee833c6c2016-11-08 18:31:04 +00003100 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003101 Operands.push_back(
3102 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3103 return MatchOperand_Success;
3104 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003105
Nirav Davee833c6c2016-11-08 18:31:04 +00003106 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003107
3108 if (Parser.getTok().isNot(AsmToken::Integer)) {
3109 Error(getLoc(), "index must be absent or #0");
3110 return MatchOperand_ParseFail;
3111 }
3112
3113 const MCExpr *ImmVal;
3114 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3115 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3116 Error(getLoc(), "index must be absent or #0");
3117 return MatchOperand_ParseFail;
3118 }
3119
3120 Operands.push_back(
3121 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3122 return MatchOperand_Success;
3123}
3124
3125/// parseOperand - Parse a arm instruction operand. For now this parses the
3126/// operand regardless of the mnemonic.
3127bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3128 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003129 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003130 // Check if the current operand has a custom associated parser, if so, try to
3131 // custom parse the operand, or fallback to the general approach.
3132 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3133 if (ResTy == MatchOperand_Success)
3134 return false;
3135 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3136 // there was a match, but an error occurred, in which case, just return that
3137 // the operand parsing failed.
3138 if (ResTy == MatchOperand_ParseFail)
3139 return true;
3140
3141 // Nothing custom, so do general case parsing.
3142 SMLoc S, E;
3143 switch (getLexer().getKind()) {
3144 default: {
3145 SMLoc S = getLoc();
3146 const MCExpr *Expr;
3147 if (parseSymbolicImmVal(Expr))
3148 return Error(S, "invalid operand");
3149
3150 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3151 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3152 return false;
3153 }
3154 case AsmToken::LBrac: {
3155 SMLoc Loc = Parser.getTok().getLoc();
3156 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3157 getContext()));
3158 Parser.Lex(); // Eat '['
3159
3160 // There's no comma after a '[', so we can parse the next operand
3161 // immediately.
3162 return parseOperand(Operands, false, false);
3163 }
3164 case AsmToken::LCurly:
3165 return parseVectorList(Operands);
3166 case AsmToken::Identifier: {
3167 // If we're expecting a Condition Code operand, then just parse that.
3168 if (isCondCode)
3169 return parseCondCode(Operands, invertCondCode);
3170
3171 // If it's a register name, parse it.
3172 if (!parseRegister(Operands))
3173 return false;
3174
3175 // This could be an optional "shift" or "extend" operand.
3176 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3177 // We can only continue if no tokens were eaten.
3178 if (GotShift != MatchOperand_NoMatch)
3179 return GotShift;
3180
3181 // This was not a register so parse other operands that start with an
3182 // identifier (like labels) as expressions and create them as immediates.
3183 const MCExpr *IdVal;
3184 S = getLoc();
3185 if (getParser().parseExpression(IdVal))
3186 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003187 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3188 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3189 return false;
3190 }
3191 case AsmToken::Integer:
3192 case AsmToken::Real:
3193 case AsmToken::Hash: {
3194 // #42 -> immediate.
3195 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003196
3197 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003198
3199 // Parse a negative sign
3200 bool isNegative = false;
3201 if (Parser.getTok().is(AsmToken::Minus)) {
3202 isNegative = true;
3203 // We need to consume this token only when we have a Real, otherwise
3204 // we let parseSymbolicImmVal take care of it
3205 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3206 Parser.Lex();
3207 }
3208
3209 // The only Real that should come through here is a literal #0.0 for
3210 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3211 // so convert the value.
3212 const AsmToken &Tok = Parser.getTok();
3213 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003214 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003215 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3216 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3217 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3218 Mnemonic != "fcmlt")
3219 return TokError("unexpected floating point literal");
3220 else if (IntVal != 0 || isNegative)
3221 return TokError("expected floating-point constant #0.0");
3222 Parser.Lex(); // Eat the token.
3223
3224 Operands.push_back(
3225 AArch64Operand::CreateToken("#0", false, S, getContext()));
3226 Operands.push_back(
3227 AArch64Operand::CreateToken(".0", false, S, getContext()));
3228 return false;
3229 }
3230
3231 const MCExpr *ImmVal;
3232 if (parseSymbolicImmVal(ImmVal))
3233 return true;
3234
3235 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3236 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3237 return false;
3238 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003239 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003240 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003241 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003242 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003243 Parser.Lex(); // Eat '='
3244 const MCExpr *SubExprVal;
3245 if (getParser().parseExpression(SubExprVal))
3246 return true;
3247
David Peixottoae5ba762014-07-18 16:05:14 +00003248 if (Operands.size() < 2 ||
3249 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003250 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003251
3252 bool IsXReg =
3253 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3254 Operands[1]->getReg());
3255
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003256 MCContext& Ctx = getContext();
3257 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3258 // 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 +00003259 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003260 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3261 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3262 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3263 ShiftAmt += 16;
3264 Imm >>= 16;
3265 }
3266 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3267 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3268 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003269 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003270 if (ShiftAmt)
3271 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3272 ShiftAmt, true, S, E, Ctx));
3273 return false;
3274 }
David Peixottoae5ba762014-07-18 16:05:14 +00003275 APInt Simm = APInt(64, Imm << ShiftAmt);
3276 // check if the immediate is an unsigned or signed 32-bit int for W regs
3277 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3278 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003279 }
3280 // 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 +00003281 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003282 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003283 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3284 return false;
3285 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003286 }
3287}
3288
3289/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3290/// operands.
3291bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3292 StringRef Name, SMLoc NameLoc,
3293 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003294 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003295 Name = StringSwitch<StringRef>(Name.lower())
3296 .Case("beq", "b.eq")
3297 .Case("bne", "b.ne")
3298 .Case("bhs", "b.hs")
3299 .Case("bcs", "b.cs")
3300 .Case("blo", "b.lo")
3301 .Case("bcc", "b.cc")
3302 .Case("bmi", "b.mi")
3303 .Case("bpl", "b.pl")
3304 .Case("bvs", "b.vs")
3305 .Case("bvc", "b.vc")
3306 .Case("bhi", "b.hi")
3307 .Case("bls", "b.ls")
3308 .Case("bge", "b.ge")
3309 .Case("blt", "b.lt")
3310 .Case("bgt", "b.gt")
3311 .Case("ble", "b.le")
3312 .Case("bal", "b.al")
3313 .Case("bnv", "b.nv")
3314 .Default(Name);
3315
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003316 // First check for the AArch64-specific .req directive.
3317 if (Parser.getTok().is(AsmToken::Identifier) &&
3318 Parser.getTok().getIdentifier() == ".req") {
3319 parseDirectiveReq(Name, NameLoc);
3320 // We always return 'error' for this, as we're done with this
3321 // statement and don't need to match the 'instruction."
3322 return true;
3323 }
3324
Tim Northover3b0846e2014-05-24 12:50:23 +00003325 // Create the leading tokens for the mnemonic, split by '.' characters.
3326 size_t Start = 0, Next = Name.find('.');
3327 StringRef Head = Name.slice(Start, Next);
3328
3329 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003330 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3331 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003332
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;
Nirav Davee833c6c2016-11-08 18:31:04 +00003390 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003391 // Parse and remember the operand.
3392 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3393 (N == 3 && condCodeThirdOperand) ||
3394 (N == 2 && condCodeSecondOperand),
3395 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003396 return true;
3397 }
3398
3399 // After successfully parsing some operands there are two special cases to
3400 // consider (i.e. notional operands not separated by commas). Both are due
3401 // to memory specifiers:
3402 // + An RBrac will end an address for load/store/prefetch
3403 // + An '!' will indicate a pre-indexed operation.
3404 //
3405 // It's someone else's responsibility to make sure these tokens are sane
3406 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003407
Nirav Davee833c6c2016-11-08 18:31:04 +00003408 SMLoc RLoc = Parser.getTok().getLoc();
3409 if (parseOptionalToken(AsmToken::RBrac))
3410 Operands.push_back(
3411 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3412 SMLoc ELoc = Parser.getTok().getLoc();
3413 if (parseOptionalToken(AsmToken::Exclaim))
3414 Operands.push_back(
3415 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003416
3417 ++N;
3418 }
3419 }
3420
Nirav Davee833c6c2016-11-08 18:31:04 +00003421 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3422 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003423
Tim Northover3b0846e2014-05-24 12:50:23 +00003424 return false;
3425}
3426
3427// FIXME: This entire function is a giant hack to provide us with decent
3428// operand range validation/diagnostics until TableGen/MC can be extended
3429// to support autogeneration of this kind of validation.
3430bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3431 SmallVectorImpl<SMLoc> &Loc) {
3432 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3433 // Check for indexed addressing modes w/ the base register being the
3434 // same as a destination/source register or pair load where
3435 // the Rt == Rt2. All of those are undefined behaviour.
3436 switch (Inst.getOpcode()) {
3437 case AArch64::LDPSWpre:
3438 case AArch64::LDPWpost:
3439 case AArch64::LDPWpre:
3440 case AArch64::LDPXpost:
3441 case AArch64::LDPXpre: {
3442 unsigned Rt = Inst.getOperand(1).getReg();
3443 unsigned Rt2 = Inst.getOperand(2).getReg();
3444 unsigned Rn = Inst.getOperand(3).getReg();
3445 if (RI->isSubRegisterEq(Rn, Rt))
3446 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3447 "is also a destination");
3448 if (RI->isSubRegisterEq(Rn, Rt2))
3449 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3450 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003451 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003452 }
3453 case AArch64::LDPDi:
3454 case AArch64::LDPQi:
3455 case AArch64::LDPSi:
3456 case AArch64::LDPSWi:
3457 case AArch64::LDPWi:
3458 case AArch64::LDPXi: {
3459 unsigned Rt = Inst.getOperand(0).getReg();
3460 unsigned Rt2 = Inst.getOperand(1).getReg();
3461 if (Rt == Rt2)
3462 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3463 break;
3464 }
3465 case AArch64::LDPDpost:
3466 case AArch64::LDPDpre:
3467 case AArch64::LDPQpost:
3468 case AArch64::LDPQpre:
3469 case AArch64::LDPSpost:
3470 case AArch64::LDPSpre:
3471 case AArch64::LDPSWpost: {
3472 unsigned Rt = Inst.getOperand(1).getReg();
3473 unsigned Rt2 = Inst.getOperand(2).getReg();
3474 if (Rt == Rt2)
3475 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3476 break;
3477 }
3478 case AArch64::STPDpost:
3479 case AArch64::STPDpre:
3480 case AArch64::STPQpost:
3481 case AArch64::STPQpre:
3482 case AArch64::STPSpost:
3483 case AArch64::STPSpre:
3484 case AArch64::STPWpost:
3485 case AArch64::STPWpre:
3486 case AArch64::STPXpost:
3487 case AArch64::STPXpre: {
3488 unsigned Rt = Inst.getOperand(1).getReg();
3489 unsigned Rt2 = Inst.getOperand(2).getReg();
3490 unsigned Rn = Inst.getOperand(3).getReg();
3491 if (RI->isSubRegisterEq(Rn, Rt))
3492 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3493 "is also a source");
3494 if (RI->isSubRegisterEq(Rn, Rt2))
3495 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3496 "is also a source");
3497 break;
3498 }
3499 case AArch64::LDRBBpre:
3500 case AArch64::LDRBpre:
3501 case AArch64::LDRHHpre:
3502 case AArch64::LDRHpre:
3503 case AArch64::LDRSBWpre:
3504 case AArch64::LDRSBXpre:
3505 case AArch64::LDRSHWpre:
3506 case AArch64::LDRSHXpre:
3507 case AArch64::LDRSWpre:
3508 case AArch64::LDRWpre:
3509 case AArch64::LDRXpre:
3510 case AArch64::LDRBBpost:
3511 case AArch64::LDRBpost:
3512 case AArch64::LDRHHpost:
3513 case AArch64::LDRHpost:
3514 case AArch64::LDRSBWpost:
3515 case AArch64::LDRSBXpost:
3516 case AArch64::LDRSHWpost:
3517 case AArch64::LDRSHXpost:
3518 case AArch64::LDRSWpost:
3519 case AArch64::LDRWpost:
3520 case AArch64::LDRXpost: {
3521 unsigned Rt = Inst.getOperand(1).getReg();
3522 unsigned Rn = Inst.getOperand(2).getReg();
3523 if (RI->isSubRegisterEq(Rn, Rt))
3524 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3525 "is also a source");
3526 break;
3527 }
3528 case AArch64::STRBBpost:
3529 case AArch64::STRBpost:
3530 case AArch64::STRHHpost:
3531 case AArch64::STRHpost:
3532 case AArch64::STRWpost:
3533 case AArch64::STRXpost:
3534 case AArch64::STRBBpre:
3535 case AArch64::STRBpre:
3536 case AArch64::STRHHpre:
3537 case AArch64::STRHpre:
3538 case AArch64::STRWpre:
3539 case AArch64::STRXpre: {
3540 unsigned Rt = Inst.getOperand(1).getReg();
3541 unsigned Rn = Inst.getOperand(2).getReg();
3542 if (RI->isSubRegisterEq(Rn, Rt))
3543 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3544 "is also a source");
3545 break;
3546 }
3547 }
3548
3549 // Now check immediate ranges. Separate from the above as there is overlap
3550 // in the instructions being checked and this keeps the nested conditionals
3551 // to a minimum.
3552 switch (Inst.getOpcode()) {
3553 case AArch64::ADDSWri:
3554 case AArch64::ADDSXri:
3555 case AArch64::ADDWri:
3556 case AArch64::ADDXri:
3557 case AArch64::SUBSWri:
3558 case AArch64::SUBSXri:
3559 case AArch64::SUBWri:
3560 case AArch64::SUBXri: {
3561 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3562 // some slight duplication here.
3563 if (Inst.getOperand(2).isExpr()) {
3564 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3565 AArch64MCExpr::VariantKind ELFRefKind;
3566 MCSymbolRefExpr::VariantKind DarwinRefKind;
3567 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003568 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3569
3570 // Only allow these with ADDXri.
3571 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3572 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3573 Inst.getOpcode() == AArch64::ADDXri)
3574 return false;
3575
3576 // Only allow these with ADDXri/ADDWri
3577 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3578 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3579 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3580 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3581 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3582 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3583 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3584 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3585 (Inst.getOpcode() == AArch64::ADDXri ||
3586 Inst.getOpcode() == AArch64::ADDWri))
3587 return false;
3588
3589 // Don't allow symbol refs in the immediate field otherwise
3590 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3591 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3592 // 'cmp w0, 'borked')
3593 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003594 }
Diana Picusc93518d2016-10-11 09:17:47 +00003595 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003596 }
3597 return false;
3598 }
3599 default:
3600 return false;
3601 }
3602}
3603
3604bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
3605 switch (ErrCode) {
3606 case Match_MissingFeature:
3607 return Error(Loc,
3608 "instruction requires a CPU feature not currently enabled");
3609 case Match_InvalidOperand:
3610 return Error(Loc, "invalid operand for instruction");
3611 case Match_InvalidSuffix:
3612 return Error(Loc, "invalid type suffix for instruction");
3613 case Match_InvalidCondCode:
3614 return Error(Loc, "expected AArch64 condition code");
3615 case Match_AddSubRegExtendSmall:
3616 return Error(Loc,
3617 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3618 case Match_AddSubRegExtendLarge:
3619 return Error(Loc,
3620 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3621 case Match_AddSubSecondSource:
3622 return Error(Loc,
3623 "expected compatible register, symbol or integer in range [0, 4095]");
3624 case Match_LogicalSecondSource:
3625 return Error(Loc, "expected compatible register or logical immediate");
3626 case Match_InvalidMovImm32Shift:
3627 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3628 case Match_InvalidMovImm64Shift:
3629 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3630 case Match_AddSubRegShift32:
3631 return Error(Loc,
3632 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3633 case Match_AddSubRegShift64:
3634 return Error(Loc,
3635 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3636 case Match_InvalidFPImm:
3637 return Error(Loc,
3638 "expected compatible register or floating-point constant");
3639 case Match_InvalidMemoryIndexedSImm9:
3640 return Error(Loc, "index must be an integer in range [-256, 255].");
3641 case Match_InvalidMemoryIndexed4SImm7:
3642 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3643 case Match_InvalidMemoryIndexed8SImm7:
3644 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3645 case Match_InvalidMemoryIndexed16SImm7:
3646 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3647 case Match_InvalidMemoryWExtend8:
3648 return Error(Loc,
3649 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3650 case Match_InvalidMemoryWExtend16:
3651 return Error(Loc,
3652 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3653 case Match_InvalidMemoryWExtend32:
3654 return Error(Loc,
3655 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3656 case Match_InvalidMemoryWExtend64:
3657 return Error(Loc,
3658 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3659 case Match_InvalidMemoryWExtend128:
3660 return Error(Loc,
3661 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3662 case Match_InvalidMemoryXExtend8:
3663 return Error(Loc,
3664 "expected 'lsl' or 'sxtx' with optional shift of #0");
3665 case Match_InvalidMemoryXExtend16:
3666 return Error(Loc,
3667 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3668 case Match_InvalidMemoryXExtend32:
3669 return Error(Loc,
3670 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3671 case Match_InvalidMemoryXExtend64:
3672 return Error(Loc,
3673 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3674 case Match_InvalidMemoryXExtend128:
3675 return Error(Loc,
3676 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3677 case Match_InvalidMemoryIndexed1:
3678 return Error(Loc, "index must be an integer in range [0, 4095].");
3679 case Match_InvalidMemoryIndexed2:
3680 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3681 case Match_InvalidMemoryIndexed4:
3682 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3683 case Match_InvalidMemoryIndexed8:
3684 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3685 case Match_InvalidMemoryIndexed16:
3686 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003687 case Match_InvalidImm0_1:
3688 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003689 case Match_InvalidImm0_7:
3690 return Error(Loc, "immediate must be an integer in range [0, 7].");
3691 case Match_InvalidImm0_15:
3692 return Error(Loc, "immediate must be an integer in range [0, 15].");
3693 case Match_InvalidImm0_31:
3694 return Error(Loc, "immediate must be an integer in range [0, 31].");
3695 case Match_InvalidImm0_63:
3696 return Error(Loc, "immediate must be an integer in range [0, 63].");
3697 case Match_InvalidImm0_127:
3698 return Error(Loc, "immediate must be an integer in range [0, 127].");
3699 case Match_InvalidImm0_65535:
3700 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3701 case Match_InvalidImm1_8:
3702 return Error(Loc, "immediate must be an integer in range [1, 8].");
3703 case Match_InvalidImm1_16:
3704 return Error(Loc, "immediate must be an integer in range [1, 16].");
3705 case Match_InvalidImm1_32:
3706 return Error(Loc, "immediate must be an integer in range [1, 32].");
3707 case Match_InvalidImm1_64:
3708 return Error(Loc, "immediate must be an integer in range [1, 64].");
3709 case Match_InvalidIndex1:
3710 return Error(Loc, "expected lane specifier '[1]'");
3711 case Match_InvalidIndexB:
3712 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3713 case Match_InvalidIndexH:
3714 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3715 case Match_InvalidIndexS:
3716 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3717 case Match_InvalidIndexD:
3718 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3719 case Match_InvalidLabel:
3720 return Error(Loc, "expected label or encodable integer pc offset");
3721 case Match_MRS:
3722 return Error(Loc, "expected readable system register");
3723 case Match_MSR:
3724 return Error(Loc, "expected writable system register or pstate");
3725 case Match_MnemonicFail:
3726 return Error(Loc, "unrecognized instruction mnemonic");
3727 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003728 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003729 }
3730}
3731
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003732static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003733
3734bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3735 OperandVector &Operands,
3736 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003737 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003738 bool MatchingInlineAsm) {
3739 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003740 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3741 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003742
David Blaikie960ea3f2014-06-08 16:18:35 +00003743 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003744 unsigned NumOperands = Operands.size();
3745
3746 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003747 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3748 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3749 if (Op2.isReg() && Op3.isImm()) {
3750 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003751 if (Op3CE) {
3752 uint64_t Op3Val = Op3CE->getValue();
3753 uint64_t NewOp3Val = 0;
3754 uint64_t NewOp4Val = 0;
3755 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003756 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003757 NewOp3Val = (32 - Op3Val) & 0x1f;
3758 NewOp4Val = 31 - Op3Val;
3759 } else {
3760 NewOp3Val = (64 - Op3Val) & 0x3f;
3761 NewOp4Val = 63 - Op3Val;
3762 }
3763
Jim Grosbach13760bd2015-05-30 01:25:56 +00003764 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3765 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003766
3767 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003768 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003769 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003770 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3771 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3772 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003773 }
3774 }
Tim Northover03b99f62015-04-30 18:28:58 +00003775 } else if (NumOperands == 4 && Tok == "bfc") {
3776 // FIXME: Horrible hack to handle BFC->BFM alias.
3777 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3778 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3779 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3780
3781 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3782 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3783 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3784
3785 if (LSBCE && WidthCE) {
3786 uint64_t LSB = LSBCE->getValue();
3787 uint64_t Width = WidthCE->getValue();
3788
3789 uint64_t RegWidth = 0;
3790 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3791 Op1.getReg()))
3792 RegWidth = 64;
3793 else
3794 RegWidth = 32;
3795
3796 if (LSB >= RegWidth)
3797 return Error(LSBOp.getStartLoc(),
3798 "expected integer in range [0, 31]");
3799 if (Width < 1 || Width > RegWidth)
3800 return Error(WidthOp.getStartLoc(),
3801 "expected integer in range [1, 32]");
3802
3803 uint64_t ImmR = 0;
3804 if (RegWidth == 32)
3805 ImmR = (32 - LSB) & 0x1f;
3806 else
3807 ImmR = (64 - LSB) & 0x3f;
3808
3809 uint64_t ImmS = Width - 1;
3810
3811 if (ImmR != 0 && ImmS >= ImmR)
3812 return Error(WidthOp.getStartLoc(),
3813 "requested insert overflows register");
3814
Jim Grosbach13760bd2015-05-30 01:25:56 +00003815 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3816 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003817 Operands[0] = AArch64Operand::CreateToken(
3818 "bfm", false, Op.getStartLoc(), getContext());
3819 Operands[2] = AArch64Operand::CreateReg(
3820 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3821 SMLoc(), getContext());
3822 Operands[3] = AArch64Operand::CreateImm(
3823 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3824 Operands.emplace_back(
3825 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3826 WidthOp.getEndLoc(), getContext()));
3827 }
3828 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003829 } else if (NumOperands == 5) {
3830 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3831 // UBFIZ -> UBFM aliases.
3832 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003833 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3834 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3835 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003836
David Blaikie960ea3f2014-06-08 16:18:35 +00003837 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3838 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3839 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003840
3841 if (Op3CE && Op4CE) {
3842 uint64_t Op3Val = Op3CE->getValue();
3843 uint64_t Op4Val = Op4CE->getValue();
3844
3845 uint64_t RegWidth = 0;
3846 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003847 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003848 RegWidth = 64;
3849 else
3850 RegWidth = 32;
3851
3852 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003853 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003854 "expected integer in range [0, 31]");
3855 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003856 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003857 "expected integer in range [1, 32]");
3858
3859 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003860 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 NewOp3Val = (32 - Op3Val) & 0x1f;
3862 else
3863 NewOp3Val = (64 - Op3Val) & 0x3f;
3864
3865 uint64_t NewOp4Val = Op4Val - 1;
3866
3867 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003868 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003869 "requested insert overflows register");
3870
3871 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003872 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003873 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003874 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003875 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003876 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003877 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003878 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003879 if (Tok == "bfi")
3880 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003881 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003882 else if (Tok == "sbfiz")
3883 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003884 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003885 else if (Tok == "ubfiz")
3886 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003887 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003888 else
3889 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003890 }
3891 }
3892
3893 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3894 // UBFX -> UBFM aliases.
3895 } else if (NumOperands == 5 &&
3896 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003897 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3898 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3899 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003900
David Blaikie960ea3f2014-06-08 16:18:35 +00003901 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3902 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3903 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003904
3905 if (Op3CE && Op4CE) {
3906 uint64_t Op3Val = Op3CE->getValue();
3907 uint64_t Op4Val = Op4CE->getValue();
3908
3909 uint64_t RegWidth = 0;
3910 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003911 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003912 RegWidth = 64;
3913 else
3914 RegWidth = 32;
3915
3916 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003917 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003918 "expected integer in range [0, 31]");
3919 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003920 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003921 "expected integer in range [1, 32]");
3922
3923 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3924
3925 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003926 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003927 "requested extract overflows register");
3928
3929 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003930 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003931 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003932 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003933 if (Tok == "bfxil")
3934 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003935 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003936 else if (Tok == "sbfx")
3937 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003938 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003939 else if (Tok == "ubfx")
3940 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003941 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003942 else
3943 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003944 }
3945 }
3946 }
3947 }
3948 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3949 // InstAlias can't quite handle this since the reg classes aren't
3950 // subclasses.
3951 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3952 // The source register can be Wn here, but the matcher expects a
3953 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003954 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3955 if (Op.isReg()) {
3956 unsigned Reg = getXRegFromWReg(Op.getReg());
3957 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3958 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003959 }
3960 }
3961 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3962 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003963 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3964 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003965 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003966 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003967 // The source register can be Wn here, but the matcher expects a
3968 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003969 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3970 if (Op.isReg()) {
3971 unsigned Reg = getXRegFromWReg(Op.getReg());
3972 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3973 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003974 }
3975 }
3976 }
3977 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3978 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003979 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3980 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003981 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003982 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003983 // The source register can be Wn here, but the matcher expects a
3984 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003985 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3986 if (Op.isReg()) {
3987 unsigned Reg = getWRegFromXReg(Op.getReg());
3988 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3989 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003990 }
3991 }
3992 }
3993
3994 // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
3995 if (NumOperands == 3 && Tok == "fmov") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003996 AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
3997 AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
3998 if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003999 unsigned zreg =
Oliver Stannardb25914e2015-11-27 13:04:48 +00004000 !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004001 RegOp.getReg())
Tim Northover3b0846e2014-05-24 12:50:23 +00004002 ? AArch64::WZR
4003 : AArch64::XZR;
David Blaikie960ea3f2014-06-08 16:18:35 +00004004 Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
4005 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004006 }
4007 }
4008
4009 MCInst Inst;
4010 // First try to match against the secondary set of tables containing the
4011 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4012 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004013 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004014
4015 // If that fails, try against the alternate table containing long-form NEON:
4016 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004017 if (MatchResult != Match_Success) {
4018 // But first, save the short-form match result: we can use it in case the
4019 // long-form match also fails.
4020 auto ShortFormNEONErrorInfo = ErrorInfo;
4021 auto ShortFormNEONMatchResult = MatchResult;
4022
Tim Northover3b0846e2014-05-24 12:50:23 +00004023 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004024 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004025
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004026 // Now, both matches failed, and the long-form match failed on the mnemonic
4027 // suffix token operand. The short-form match failure is probably more
4028 // relevant: use it instead.
4029 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004030 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004031 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4032 MatchResult = ShortFormNEONMatchResult;
4033 ErrorInfo = ShortFormNEONErrorInfo;
4034 }
4035 }
4036
Tim Northover3b0846e2014-05-24 12:50:23 +00004037 switch (MatchResult) {
4038 case Match_Success: {
4039 // Perform range checking and other semantic validations
4040 SmallVector<SMLoc, 8> OperandLocs;
4041 NumOperands = Operands.size();
4042 for (unsigned i = 1; i < NumOperands; ++i)
4043 OperandLocs.push_back(Operands[i]->getStartLoc());
4044 if (validateInstruction(Inst, OperandLocs))
4045 return true;
4046
4047 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004048 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004049 return false;
4050 }
4051 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004052 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004053 // Special case the error message for the very common case where only
4054 // a single subtarget feature is missing (neon, e.g.).
4055 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004056 uint64_t Mask = 1;
4057 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4058 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004059 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004060 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004061 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004062 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004063 }
4064 return Error(IDLoc, Msg);
4065 }
4066 case Match_MnemonicFail:
4067 return showMatchError(IDLoc, MatchResult);
4068 case Match_InvalidOperand: {
4069 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004070
Tim Northover26bb14e2014-08-18 11:49:42 +00004071 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004072 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004073 return Error(IDLoc, "too few operands for instruction",
4074 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004075
David Blaikie960ea3f2014-06-08 16:18:35 +00004076 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004077 if (ErrorLoc == SMLoc())
4078 ErrorLoc = IDLoc;
4079 }
4080 // If the match failed on a suffix token operand, tweak the diagnostic
4081 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004082 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4083 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004084 MatchResult = Match_InvalidSuffix;
4085
4086 return showMatchError(ErrorLoc, MatchResult);
4087 }
4088 case Match_InvalidMemoryIndexed1:
4089 case Match_InvalidMemoryIndexed2:
4090 case Match_InvalidMemoryIndexed4:
4091 case Match_InvalidMemoryIndexed8:
4092 case Match_InvalidMemoryIndexed16:
4093 case Match_InvalidCondCode:
4094 case Match_AddSubRegExtendSmall:
4095 case Match_AddSubRegExtendLarge:
4096 case Match_AddSubSecondSource:
4097 case Match_LogicalSecondSource:
4098 case Match_AddSubRegShift32:
4099 case Match_AddSubRegShift64:
4100 case Match_InvalidMovImm32Shift:
4101 case Match_InvalidMovImm64Shift:
4102 case Match_InvalidFPImm:
4103 case Match_InvalidMemoryWExtend8:
4104 case Match_InvalidMemoryWExtend16:
4105 case Match_InvalidMemoryWExtend32:
4106 case Match_InvalidMemoryWExtend64:
4107 case Match_InvalidMemoryWExtend128:
4108 case Match_InvalidMemoryXExtend8:
4109 case Match_InvalidMemoryXExtend16:
4110 case Match_InvalidMemoryXExtend32:
4111 case Match_InvalidMemoryXExtend64:
4112 case Match_InvalidMemoryXExtend128:
4113 case Match_InvalidMemoryIndexed4SImm7:
4114 case Match_InvalidMemoryIndexed8SImm7:
4115 case Match_InvalidMemoryIndexed16SImm7:
4116 case Match_InvalidMemoryIndexedSImm9:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004117 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004118 case Match_InvalidImm0_7:
4119 case Match_InvalidImm0_15:
4120 case Match_InvalidImm0_31:
4121 case Match_InvalidImm0_63:
4122 case Match_InvalidImm0_127:
4123 case Match_InvalidImm0_65535:
4124 case Match_InvalidImm1_8:
4125 case Match_InvalidImm1_16:
4126 case Match_InvalidImm1_32:
4127 case Match_InvalidImm1_64:
4128 case Match_InvalidIndex1:
4129 case Match_InvalidIndexB:
4130 case Match_InvalidIndexH:
4131 case Match_InvalidIndexS:
4132 case Match_InvalidIndexD:
4133 case Match_InvalidLabel:
4134 case Match_MSR:
4135 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004136 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004137 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004138 // Any time we get here, there's nothing fancy to do. Just get the
4139 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004140 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 if (ErrorLoc == SMLoc())
4142 ErrorLoc = IDLoc;
4143 return showMatchError(ErrorLoc, MatchResult);
4144 }
4145 }
4146
4147 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004148}
4149
4150/// ParseDirective parses the arm specific directives
4151bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004152 const MCObjectFileInfo::Environment Format =
4153 getContext().getObjectFileInfo()->getObjectFileType();
4154 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4155 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004156
Tim Northover3b0846e2014-05-24 12:50:23 +00004157 StringRef IDVal = DirectiveID.getIdentifier();
4158 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004159 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004160 parseDirectiveArch(Loc);
4161 else if (IDVal == ".cpu")
4162 parseDirectiveCPU(Loc);
4163 else if (IDVal == ".hword")
4164 parseDirectiveWord(2, Loc);
4165 else if (IDVal == ".word")
4166 parseDirectiveWord(4, Loc);
4167 else if (IDVal == ".xword")
4168 parseDirectiveWord(8, Loc);
4169 else if (IDVal == ".tlsdesccall")
4170 parseDirectiveTLSDescCall(Loc);
4171 else if (IDVal == ".ltorg" || IDVal == ".pool")
4172 parseDirectiveLtorg(Loc);
4173 else if (IDVal == ".unreq")
4174 parseDirectiveUnreq(Loc);
4175 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004176 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004177 parseDirectiveInst(Loc);
4178 else
4179 return true;
4180 } else if (IDVal == MCLOHDirectiveName())
4181 parseDirectiveLOH(IDVal, Loc);
4182 else
4183 return true;
4184 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004185}
4186
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004187static const struct {
4188 const char *Name;
4189 const FeatureBitset Features;
4190} ExtensionMap[] = {
4191 { "crc", {AArch64::FeatureCRC} },
4192 { "crypto", {AArch64::FeatureCrypto} },
4193 { "fp", {AArch64::FeatureFPARMv8} },
4194 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004195 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004196 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004197
4198 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004199 { "pan", {} },
4200 { "lor", {} },
4201 { "rdma", {} },
4202 { "profile", {} },
4203};
4204
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004205/// parseDirectiveArch
4206/// ::= .arch token
4207bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4208 SMLoc ArchLoc = getLoc();
4209
4210 StringRef Arch, ExtensionString;
4211 std::tie(Arch, ExtensionString) =
4212 getParser().parseStringToEndOfStatement().trim().split('+');
4213
4214 unsigned ID = AArch64::parseArch(Arch);
Nirav Davee833c6c2016-11-08 18:31:04 +00004215 if (ID == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID))
4216 return Error(ArchLoc, "unknown arch name");
4217
4218 if (parseToken(AsmToken::EndOfStatement))
4219 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004220
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004221 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004222 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004223 AArch64::getArchFeatures(ID, AArch64Features);
4224 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4225 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004226
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004227 MCSubtargetInfo &STI = copySTI();
4228 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4229 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4230
4231 SmallVector<StringRef, 4> RequestedExtensions;
4232 if (!ExtensionString.empty())
4233 ExtensionString.split(RequestedExtensions, '+');
4234
4235 FeatureBitset Features = STI.getFeatureBits();
4236 for (auto Name : RequestedExtensions) {
4237 bool EnableFeature = true;
4238
4239 if (Name.startswith_lower("no")) {
4240 EnableFeature = false;
4241 Name = Name.substr(2);
4242 }
4243
4244 for (const auto &Extension : ExtensionMap) {
4245 if (Extension.Name != Name)
4246 continue;
4247
4248 if (Extension.Features.none())
4249 report_fatal_error("unsupported architectural extension: " + Name);
4250
4251 FeatureBitset ToggleFeatures = EnableFeature
4252 ? (~Features & Extension.Features)
4253 : ( Features & Extension.Features);
4254 uint64_t Features =
4255 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4256 setAvailableFeatures(Features);
4257 break;
4258 }
4259 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004260 return false;
4261}
4262
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004263/// parseDirectiveCPU
4264/// ::= .cpu id
4265bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
4266 SMLoc CPULoc = getLoc();
4267
4268 StringRef CPU, ExtensionString;
4269 std::tie(CPU, ExtensionString) =
4270 getParser().parseStringToEndOfStatement().trim().split('+');
4271
Nirav Davee833c6c2016-11-08 18:31:04 +00004272 if (parseToken(AsmToken::EndOfStatement))
4273 return true;
4274
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004275 SmallVector<StringRef, 4> RequestedExtensions;
4276 if (!ExtensionString.empty())
4277 ExtensionString.split(RequestedExtensions, '+');
4278
4279 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4280 // once that is tablegen'ed
4281 if (!getSTI().isCPUStringValid(CPU)) {
4282 Error(CPULoc, "unknown CPU name");
4283 return false;
4284 }
4285
4286 MCSubtargetInfo &STI = copySTI();
4287 STI.setDefaultFeatures(CPU, "");
4288
4289 FeatureBitset Features = STI.getFeatureBits();
4290 for (auto Name : RequestedExtensions) {
4291 bool EnableFeature = true;
4292
4293 if (Name.startswith_lower("no")) {
4294 EnableFeature = false;
4295 Name = Name.substr(2);
4296 }
4297
4298 for (const auto &Extension : ExtensionMap) {
4299 if (Extension.Name != Name)
4300 continue;
4301
4302 if (Extension.Features.none())
4303 report_fatal_error("unsupported architectural extension: " + Name);
4304
4305 FeatureBitset ToggleFeatures = EnableFeature
4306 ? (~Features & Extension.Features)
4307 : ( Features & Extension.Features);
4308 uint64_t Features =
4309 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4310 setAvailableFeatures(Features);
4311
4312 break;
4313 }
4314 }
4315 return false;
4316}
4317
Tim Northover3b0846e2014-05-24 12:50:23 +00004318/// parseDirectiveWord
4319/// ::= .word [ expression (, expression)* ]
4320bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004321 auto parseOp = [&]() -> bool {
4322 const MCExpr *Value;
4323 if (getParser().parseExpression(Value))
4324 return true;
4325 getParser().getStreamer().EmitValue(Value, Size, L);
4326 return false;
4327 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004328
Nirav Davee833c6c2016-11-08 18:31:04 +00004329 if (parseMany(parseOp))
4330 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004331 return false;
4332}
4333
Chad Rosierdcd2a302014-10-22 20:35:57 +00004334/// parseDirectiveInst
4335/// ::= .inst opcode [, ...]
4336bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004337 if (getLexer().is(AsmToken::EndOfStatement))
4338 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004339
Nirav Davee833c6c2016-11-08 18:31:04 +00004340 auto parseOp = [&]() -> bool {
4341 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004342 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004343 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4344 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004345 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004346 if (check(!Value, L, "expected constant expression"))
4347 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004348 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004349 return false;
4350 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004351
Nirav Davee833c6c2016-11-08 18:31:04 +00004352 if (parseMany(parseOp))
4353 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004354 return false;
4355}
4356
Tim Northover3b0846e2014-05-24 12:50:23 +00004357// parseDirectiveTLSDescCall:
4358// ::= .tlsdesccall symbol
4359bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4360 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004361 if (check(getParser().parseIdentifier(Name), L,
4362 "expected symbol after directive") ||
4363 parseToken(AsmToken::EndOfStatement))
4364 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004365
Jim Grosbach6f482002015-05-18 18:43:14 +00004366 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004367 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4368 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004369
4370 MCInst Inst;
4371 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004372 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004373
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004374 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004375 return false;
4376}
4377
4378/// ::= .loh <lohName | lohId> label1, ..., labelN
4379/// The number of arguments depends on the loh identifier.
4380bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004381 MCLOHType Kind;
4382 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4383 if (getParser().getTok().isNot(AsmToken::Integer))
4384 return TokError("expected an identifier or a number in directive");
4385 // We successfully get a numeric value for the identifier.
4386 // Check if it is valid.
4387 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004388 if (Id <= -1U && !isValidMCLOHType(Id))
4389 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004390 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004391 } else {
4392 StringRef Name = getTok().getIdentifier();
4393 // We successfully parse an identifier.
4394 // Check if it is a recognized one.
4395 int Id = MCLOHNameToId(Name);
4396
4397 if (Id == -1)
4398 return TokError("invalid identifier in directive");
4399 Kind = (MCLOHType)Id;
4400 }
4401 // Consume the identifier.
4402 Lex();
4403 // Get the number of arguments of this LOH.
4404 int NbArgs = MCLOHIdToNbArgs(Kind);
4405
4406 assert(NbArgs != -1 && "Invalid number of arguments");
4407
4408 SmallVector<MCSymbol *, 3> Args;
4409 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4410 StringRef Name;
4411 if (getParser().parseIdentifier(Name))
4412 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004413 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004414
4415 if (Idx + 1 == NbArgs)
4416 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004417 if (parseToken(AsmToken::Comma,
4418 "unexpected token in '" + Twine(IDVal) + "' directive"))
4419 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004420 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004421 if (parseToken(AsmToken::EndOfStatement,
4422 "unexpected token in '" + Twine(IDVal) + "' directive"))
4423 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004424
4425 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4426 return false;
4427}
4428
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004429/// parseDirectiveLtorg
4430/// ::= .ltorg | .pool
4431bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004432 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4433 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004434 getTargetStreamer().emitCurrentConstantPool();
4435 return false;
4436}
4437
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004438/// parseDirectiveReq
4439/// ::= name .req registername
4440bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004441 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004442 Parser.Lex(); // Eat the '.req' token.
4443 SMLoc SRegLoc = getLoc();
4444 unsigned RegNum = tryParseRegister();
4445 bool IsVector = false;
4446
4447 if (RegNum == static_cast<unsigned>(-1)) {
4448 StringRef Kind;
4449 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004450 if (!Kind.empty())
4451 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004452 IsVector = true;
4453 }
4454
Nirav Dave2364748a2016-09-16 18:30:20 +00004455 if (RegNum == static_cast<unsigned>(-1))
4456 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004457
4458 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004459 if (parseToken(AsmToken::EndOfStatement,
4460 "unexpected input in .req directive"))
4461 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004462
4463 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004464 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004465 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4466
Nirav Dave2364748a2016-09-16 18:30:20 +00004467 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004468}
4469
4470/// parseDirectiveUneq
4471/// ::= .unreq registername
4472bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004473 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004474 if (getTok().isNot(AsmToken::Identifier))
4475 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004476 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4477 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004478 if (parseToken(AsmToken::EndOfStatement))
4479 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004480 return false;
4481}
4482
Tim Northover3b0846e2014-05-24 12:50:23 +00004483bool
4484AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4485 AArch64MCExpr::VariantKind &ELFRefKind,
4486 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4487 int64_t &Addend) {
4488 ELFRefKind = AArch64MCExpr::VK_INVALID;
4489 DarwinRefKind = MCSymbolRefExpr::VK_None;
4490 Addend = 0;
4491
4492 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4493 ELFRefKind = AE->getKind();
4494 Expr = AE->getSubExpr();
4495 }
4496
4497 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4498 if (SE) {
4499 // It's a simple symbol reference with no addend.
4500 DarwinRefKind = SE->getKind();
4501 return true;
4502 }
4503
4504 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4505 if (!BE)
4506 return false;
4507
4508 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4509 if (!SE)
4510 return false;
4511 DarwinRefKind = SE->getKind();
4512
4513 if (BE->getOpcode() != MCBinaryExpr::Add &&
4514 BE->getOpcode() != MCBinaryExpr::Sub)
4515 return false;
4516
4517 // See if the addend is is a constant, otherwise there's more going
4518 // on here than we can deal with.
4519 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4520 if (!AddendExpr)
4521 return false;
4522
4523 Addend = AddendExpr->getValue();
4524 if (BE->getOpcode() == MCBinaryExpr::Sub)
4525 Addend = -Addend;
4526
4527 // It's some symbol reference + a constant addend, but really
4528 // shouldn't use both Darwin and ELF syntax.
4529 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4530 DarwinRefKind == MCSymbolRefExpr::VK_None;
4531}
4532
4533/// Force static initialization.
4534extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004535 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4536 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4537 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004538}
4539
4540#define GET_REGISTER_MATCHER
4541#define GET_SUBTARGET_FEATURE_NAME
4542#define GET_MATCHER_IMPLEMENTATION
4543#include "AArch64GenAsmMatcher.inc"
4544
4545// Define this matcher function after the auto-generated include so we
4546// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004547unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004548 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004549 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004550 // If the kind is a token for a literal immediate, check if our asm
4551 // operand matches. This is for InstAliases which have a fixed-value
4552 // immediate in the syntax.
4553 int64_t ExpectedVal;
4554 switch (Kind) {
4555 default:
4556 return Match_InvalidOperand;
4557 case MCK__35_0:
4558 ExpectedVal = 0;
4559 break;
4560 case MCK__35_1:
4561 ExpectedVal = 1;
4562 break;
4563 case MCK__35_12:
4564 ExpectedVal = 12;
4565 break;
4566 case MCK__35_16:
4567 ExpectedVal = 16;
4568 break;
4569 case MCK__35_2:
4570 ExpectedVal = 2;
4571 break;
4572 case MCK__35_24:
4573 ExpectedVal = 24;
4574 break;
4575 case MCK__35_3:
4576 ExpectedVal = 3;
4577 break;
4578 case MCK__35_32:
4579 ExpectedVal = 32;
4580 break;
4581 case MCK__35_4:
4582 ExpectedVal = 4;
4583 break;
4584 case MCK__35_48:
4585 ExpectedVal = 48;
4586 break;
4587 case MCK__35_6:
4588 ExpectedVal = 6;
4589 break;
4590 case MCK__35_64:
4591 ExpectedVal = 64;
4592 break;
4593 case MCK__35_8:
4594 ExpectedVal = 8;
4595 break;
4596 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004597 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004598 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004599 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004600 if (!CE)
4601 return Match_InvalidOperand;
4602 if (CE->getValue() == ExpectedVal)
4603 return Match_Success;
4604 return Match_InvalidOperand;
4605}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004606
Alex Bradbury58eba092016-11-01 16:32:05 +00004607OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004608AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4609
4610 SMLoc S = getLoc();
4611
4612 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4613 Error(S, "expected register");
4614 return MatchOperand_ParseFail;
4615 }
4616
4617 int FirstReg = tryParseRegister();
4618 if (FirstReg == -1) {
4619 return MatchOperand_ParseFail;
4620 }
4621 const MCRegisterClass &WRegClass =
4622 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4623 const MCRegisterClass &XRegClass =
4624 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4625
4626 bool isXReg = XRegClass.contains(FirstReg),
4627 isWReg = WRegClass.contains(FirstReg);
4628 if (!isXReg && !isWReg) {
4629 Error(S, "expected first even register of a "
4630 "consecutive same-size even/odd register pair");
4631 return MatchOperand_ParseFail;
4632 }
4633
4634 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4635 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4636
4637 if (FirstEncoding & 0x1) {
4638 Error(S, "expected first even register of a "
4639 "consecutive same-size even/odd register pair");
4640 return MatchOperand_ParseFail;
4641 }
4642
4643 SMLoc M = getLoc();
4644 if (getParser().getTok().isNot(AsmToken::Comma)) {
4645 Error(M, "expected comma");
4646 return MatchOperand_ParseFail;
4647 }
4648 // Eat the comma
4649 getParser().Lex();
4650
4651 SMLoc E = getLoc();
4652 int SecondReg = tryParseRegister();
4653 if (SecondReg ==-1) {
4654 return MatchOperand_ParseFail;
4655 }
4656
Eugene Zelenko049b0172017-01-06 00:30:53 +00004657 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004658 (isXReg && !XRegClass.contains(SecondReg)) ||
4659 (isWReg && !WRegClass.contains(SecondReg))) {
4660 Error(E,"expected second odd register of a "
4661 "consecutive same-size even/odd register pair");
4662 return MatchOperand_ParseFail;
4663 }
Joel Jones504bf332016-10-24 13:37:13 +00004664
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004665 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004666 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004667 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4668 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4669 } else {
4670 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4671 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4672 }
4673
4674 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4675 getContext()));
4676
4677 return MatchOperand_Success;
4678}