blob: de50bfb41b01a87dac65b7fff0526c188cb489c4 [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"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.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);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000077 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000078 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
79 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000080 unsigned matchRegisterNameAlias(StringRef Name, bool isVector);
Tim Northover3b0846e2014-05-24 12:50:23 +000081 int tryParseRegister();
82 int tryMatchVectorRegister(StringRef &Kind, bool expected);
83 bool parseRegister(OperandVector &Operands);
84 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
85 bool parseVectorList(OperandVector &Operands);
86 bool parseOperand(OperandVector &Operands, bool isCondCode,
87 bool invertCondCode);
88
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000089 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000090
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000091 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000092 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +000093 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +000094 bool parseDirectiveInst(SMLoc L);
95
Tim Northover3b0846e2014-05-24 12:50:23 +000096 bool parseDirectiveTLSDescCall(SMLoc L);
97
98 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000099 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000100
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000101 bool parseDirectiveReq(StringRef Name, SMLoc L);
102 bool parseDirectiveUnreq(SMLoc L);
103
Tim Northover3b0846e2014-05-24 12:50:23 +0000104 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
105 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
106 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000107 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000108 bool MatchingInlineAsm) override;
109/// @name Auto-generated Match Functions
110/// {
111
112#define GET_ASSEMBLER_HEADER
113#include "AArch64GenAsmMatcher.inc"
114
115 /// }
116
117 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
118 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
119 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
120 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
121 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
122 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000123 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000124 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
125 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
126 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
127 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
128 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
129 bool tryParseVectorRegister(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000130 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000131
132public:
133 enum AArch64MatchResultTy {
134 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
135#define GET_OPERAND_DIAGNOSTIC_TYPES
136#include "AArch64GenAsmMatcher.inc"
137 };
Joel Jones504bf332016-10-24 13:37:13 +0000138 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000139
Akira Hatanakab11ef082015-11-14 06:35:56 +0000140 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000141 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000142 : MCTargetAsmParser(Options, STI) {
Joel Jones504bf332016-10-24 13:37:13 +0000143 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000144 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000145 MCStreamer &S = getParser().getStreamer();
146 if (S.getTargetStreamer() == nullptr)
147 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000148
149 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000150 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000151 }
152
153 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
154 SMLoc NameLoc, OperandVector &Operands) override;
155 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
156 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000157 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000158 unsigned Kind) override;
159
160 static bool classifySymbolRef(const MCExpr *Expr,
161 AArch64MCExpr::VariantKind &ELFRefKind,
162 MCSymbolRefExpr::VariantKind &DarwinRefKind,
163 int64_t &Addend);
164};
Tim Northover3b0846e2014-05-24 12:50:23 +0000165
166/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
167/// instruction.
168class AArch64Operand : public MCParsedAsmOperand {
169private:
170 enum KindTy {
171 k_Immediate,
172 k_ShiftedImm,
173 k_CondCode,
174 k_Register,
175 k_VectorList,
176 k_VectorIndex,
177 k_Token,
178 k_SysReg,
179 k_SysCR,
180 k_Prefetch,
181 k_ShiftExtend,
182 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000183 k_Barrier,
184 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000185 } Kind;
186
187 SMLoc StartLoc, EndLoc;
188
189 struct TokOp {
190 const char *Data;
191 unsigned Length;
192 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
193 };
194
195 struct RegOp {
196 unsigned RegNum;
197 bool isVector;
198 };
199
200 struct VectorListOp {
201 unsigned RegNum;
202 unsigned Count;
203 unsigned NumElements;
204 unsigned ElementKind;
205 };
206
207 struct VectorIndexOp {
208 unsigned Val;
209 };
210
211 struct ImmOp {
212 const MCExpr *Val;
213 };
214
215 struct ShiftedImmOp {
216 const MCExpr *Val;
217 unsigned ShiftAmount;
218 };
219
220 struct CondCodeOp {
221 AArch64CC::CondCode Code;
222 };
223
224 struct FPImmOp {
225 unsigned Val; // Encoded 8-bit representation.
226 };
227
228 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000229 const char *Data;
230 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000231 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000232 };
233
234 struct SysRegOp {
235 const char *Data;
236 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000237 uint32_t MRSReg;
238 uint32_t MSRReg;
239 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000240 };
241
242 struct SysCRImmOp {
243 unsigned Val;
244 };
245
246 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000247 const char *Data;
248 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000249 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000250 };
251
Oliver Stannarda34e4702015-12-01 10:48:51 +0000252 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000253 const char *Data;
254 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000255 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000256 };
257
Tim Northover3b0846e2014-05-24 12:50:23 +0000258 struct ShiftExtendOp {
259 AArch64_AM::ShiftExtendType Type;
260 unsigned Amount;
261 bool HasExplicitAmount;
262 };
263
264 struct ExtendOp {
265 unsigned Val;
266 };
267
268 union {
269 struct TokOp Tok;
270 struct RegOp Reg;
271 struct VectorListOp VectorList;
272 struct VectorIndexOp VectorIndex;
273 struct ImmOp Imm;
274 struct ShiftedImmOp ShiftedImm;
275 struct CondCodeOp CondCode;
276 struct FPImmOp FPImm;
277 struct BarrierOp Barrier;
278 struct SysRegOp SysReg;
279 struct SysCRImmOp SysCRImm;
280 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000281 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000282 struct ShiftExtendOp ShiftExtend;
283 };
284
285 // Keep the MCContext around as the MCExprs may need manipulated during
286 // the add<>Operands() calls.
287 MCContext &Ctx;
288
David Blaikie960ea3f2014-06-08 16:18:35 +0000289public:
David Blaikie9f380a32015-03-16 18:06:57 +0000290 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000291
Tim Northover3b0846e2014-05-24 12:50:23 +0000292 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
293 Kind = o.Kind;
294 StartLoc = o.StartLoc;
295 EndLoc = o.EndLoc;
296 switch (Kind) {
297 case k_Token:
298 Tok = o.Tok;
299 break;
300 case k_Immediate:
301 Imm = o.Imm;
302 break;
303 case k_ShiftedImm:
304 ShiftedImm = o.ShiftedImm;
305 break;
306 case k_CondCode:
307 CondCode = o.CondCode;
308 break;
309 case k_FPImm:
310 FPImm = o.FPImm;
311 break;
312 case k_Barrier:
313 Barrier = o.Barrier;
314 break;
315 case k_Register:
316 Reg = o.Reg;
317 break;
318 case k_VectorList:
319 VectorList = o.VectorList;
320 break;
321 case k_VectorIndex:
322 VectorIndex = o.VectorIndex;
323 break;
324 case k_SysReg:
325 SysReg = o.SysReg;
326 break;
327 case k_SysCR:
328 SysCRImm = o.SysCRImm;
329 break;
330 case k_Prefetch:
331 Prefetch = o.Prefetch;
332 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000333 case k_PSBHint:
334 PSBHint = o.PSBHint;
335 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000336 case k_ShiftExtend:
337 ShiftExtend = o.ShiftExtend;
338 break;
339 }
340 }
341
342 /// getStartLoc - Get the location of the first token of this operand.
343 SMLoc getStartLoc() const override { return StartLoc; }
344 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000345 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000346
347 StringRef getToken() const {
348 assert(Kind == k_Token && "Invalid access!");
349 return StringRef(Tok.Data, Tok.Length);
350 }
351
352 bool isTokenSuffix() const {
353 assert(Kind == k_Token && "Invalid access!");
354 return Tok.IsSuffix;
355 }
356
357 const MCExpr *getImm() const {
358 assert(Kind == k_Immediate && "Invalid access!");
359 return Imm.Val;
360 }
361
362 const MCExpr *getShiftedImmVal() const {
363 assert(Kind == k_ShiftedImm && "Invalid access!");
364 return ShiftedImm.Val;
365 }
366
367 unsigned getShiftedImmShift() const {
368 assert(Kind == k_ShiftedImm && "Invalid access!");
369 return ShiftedImm.ShiftAmount;
370 }
371
372 AArch64CC::CondCode getCondCode() const {
373 assert(Kind == k_CondCode && "Invalid access!");
374 return CondCode.Code;
375 }
376
377 unsigned getFPImm() const {
378 assert(Kind == k_FPImm && "Invalid access!");
379 return FPImm.Val;
380 }
381
382 unsigned getBarrier() const {
383 assert(Kind == k_Barrier && "Invalid access!");
384 return Barrier.Val;
385 }
386
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000387 StringRef getBarrierName() const {
388 assert(Kind == k_Barrier && "Invalid access!");
389 return StringRef(Barrier.Data, Barrier.Length);
390 }
391
Tim Northover3b0846e2014-05-24 12:50:23 +0000392 unsigned getReg() const override {
393 assert(Kind == k_Register && "Invalid access!");
394 return Reg.RegNum;
395 }
396
397 unsigned getVectorListStart() const {
398 assert(Kind == k_VectorList && "Invalid access!");
399 return VectorList.RegNum;
400 }
401
402 unsigned getVectorListCount() const {
403 assert(Kind == k_VectorList && "Invalid access!");
404 return VectorList.Count;
405 }
406
407 unsigned getVectorIndex() const {
408 assert(Kind == k_VectorIndex && "Invalid access!");
409 return VectorIndex.Val;
410 }
411
412 StringRef getSysReg() const {
413 assert(Kind == k_SysReg && "Invalid access!");
414 return StringRef(SysReg.Data, SysReg.Length);
415 }
416
Tim Northover3b0846e2014-05-24 12:50:23 +0000417 unsigned getSysCR() const {
418 assert(Kind == k_SysCR && "Invalid access!");
419 return SysCRImm.Val;
420 }
421
422 unsigned getPrefetch() const {
423 assert(Kind == k_Prefetch && "Invalid access!");
424 return Prefetch.Val;
425 }
426
Oliver Stannarda34e4702015-12-01 10:48:51 +0000427 unsigned getPSBHint() const {
428 assert(Kind == k_PSBHint && "Invalid access!");
429 return PSBHint.Val;
430 }
431
432 StringRef getPSBHintName() const {
433 assert(Kind == k_PSBHint && "Invalid access!");
434 return StringRef(PSBHint.Data, PSBHint.Length);
435 }
436
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000437 StringRef getPrefetchName() const {
438 assert(Kind == k_Prefetch && "Invalid access!");
439 return StringRef(Prefetch.Data, Prefetch.Length);
440 }
441
Tim Northover3b0846e2014-05-24 12:50:23 +0000442 AArch64_AM::ShiftExtendType getShiftExtendType() const {
443 assert(Kind == k_ShiftExtend && "Invalid access!");
444 return ShiftExtend.Type;
445 }
446
447 unsigned getShiftExtendAmount() const {
448 assert(Kind == k_ShiftExtend && "Invalid access!");
449 return ShiftExtend.Amount;
450 }
451
452 bool hasShiftExtendAmount() const {
453 assert(Kind == k_ShiftExtend && "Invalid access!");
454 return ShiftExtend.HasExplicitAmount;
455 }
456
457 bool isImm() const override { return Kind == k_Immediate; }
458 bool isMem() const override { return false; }
459 bool isSImm9() const {
460 if (!isImm())
461 return false;
462 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
463 if (!MCE)
464 return false;
465 int64_t Val = MCE->getValue();
466 return (Val >= -256 && Val < 256);
467 }
Sam Parker6d42de72017-08-11 13:14:00 +0000468 bool isSImm10s8() const {
469 if (!isImm())
470 return false;
471 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
472 if (!MCE)
473 return false;
474 int64_t Val = MCE->getValue();
475 return (Val >= -4096 && Val < 4089 && (Val & 7) == 0);
476 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000477 bool isSImm7s4() const {
478 if (!isImm())
479 return false;
480 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
481 if (!MCE)
482 return false;
483 int64_t Val = MCE->getValue();
484 return (Val >= -256 && Val <= 252 && (Val & 3) == 0);
485 }
486 bool isSImm7s8() const {
487 if (!isImm())
488 return false;
489 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
490 if (!MCE)
491 return false;
492 int64_t Val = MCE->getValue();
493 return (Val >= -512 && Val <= 504 && (Val & 7) == 0);
494 }
495 bool isSImm7s16() const {
496 if (!isImm())
497 return false;
498 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
499 if (!MCE)
500 return false;
501 int64_t Val = MCE->getValue();
502 return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
503 }
504
505 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
506 AArch64MCExpr::VariantKind ELFRefKind;
507 MCSymbolRefExpr::VariantKind DarwinRefKind;
508 int64_t Addend;
509 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
510 Addend)) {
511 // If we don't understand the expression, assume the best and
512 // let the fixup and relocation code deal with it.
513 return true;
514 }
515
516 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
517 ELFRefKind == AArch64MCExpr::VK_LO12 ||
518 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
519 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
520 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
521 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
522 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
523 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
524 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
525 // Note that we don't range-check the addend. It's adjusted modulo page
526 // size when converted, so there is no "out of range" condition when using
527 // @pageoff.
528 return Addend >= 0 && (Addend % Scale) == 0;
529 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
530 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
531 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
532 return Addend == 0;
533 }
534
535 return false;
536 }
537
538 template <int Scale> bool isUImm12Offset() const {
539 if (!isImm())
540 return false;
541
542 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
543 if (!MCE)
544 return isSymbolicUImm12Offset(getImm(), Scale);
545
546 int64_t Val = MCE->getValue();
547 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
548 }
549
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000550 template <int N, int M>
551 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000552 if (!isImm())
553 return false;
554 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
555 if (!MCE)
556 return false;
557 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000558 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000559 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000560
Tim Northover3b0846e2014-05-24 12:50:23 +0000561 bool isLogicalImm32() const {
562 if (!isImm())
563 return false;
564 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
565 if (!MCE)
566 return false;
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000567 int64_t Val = MCE->getValue();
568 if (Val >> 32 != 0 && Val >> 32 != ~0LL)
569 return false;
570 Val &= 0xFFFFFFFF;
571 return AArch64_AM::isLogicalImmediate(Val, 32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000572 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000573
Tim Northover3b0846e2014-05-24 12:50:23 +0000574 bool isLogicalImm64() const {
575 if (!isImm())
576 return false;
577 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
578 if (!MCE)
579 return false;
580 return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
581 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000582
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000583 bool isLogicalImm32Not() const {
584 if (!isImm())
585 return false;
586 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
587 if (!MCE)
588 return false;
589 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
590 return AArch64_AM::isLogicalImmediate(Val, 32);
591 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000592
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000593 bool isLogicalImm64Not() const {
594 if (!isImm())
595 return false;
596 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
597 if (!MCE)
598 return false;
599 return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
600 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000601
Tim Northover3b0846e2014-05-24 12:50:23 +0000602 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000603
Tim Northover3b0846e2014-05-24 12:50:23 +0000604 bool isAddSubImm() const {
605 if (!isShiftedImm() && !isImm())
606 return false;
607
608 const MCExpr *Expr;
609
610 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
611 if (isShiftedImm()) {
612 unsigned Shift = ShiftedImm.ShiftAmount;
613 Expr = ShiftedImm.Val;
614 if (Shift != 0 && Shift != 12)
615 return false;
616 } else {
617 Expr = getImm();
618 }
619
620 AArch64MCExpr::VariantKind ELFRefKind;
621 MCSymbolRefExpr::VariantKind DarwinRefKind;
622 int64_t Addend;
623 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
624 DarwinRefKind, Addend)) {
625 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
626 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
627 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
628 || ELFRefKind == AArch64MCExpr::VK_LO12
629 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
630 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
631 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
632 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
633 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
634 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
635 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
636 }
637
Diana Picusc93518d2016-10-11 09:17:47 +0000638 // If it's a constant, it should be a real immediate in range:
639 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
640 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
641
642 // If it's an expression, we hope for the best and let the fixup/relocation
643 // code deal with it.
644 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000645 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000646
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000647 bool isAddSubImmNeg() const {
648 if (!isShiftedImm() && !isImm())
649 return false;
650
651 const MCExpr *Expr;
652
653 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
654 if (isShiftedImm()) {
655 unsigned Shift = ShiftedImm.ShiftAmount;
656 Expr = ShiftedImm.Val;
657 if (Shift != 0 && Shift != 12)
658 return false;
659 } else
660 Expr = getImm();
661
662 // Otherwise it should be a real negative immediate in range:
663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
664 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
665 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000666
Tim Northover3b0846e2014-05-24 12:50:23 +0000667 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000668
Tim Northover3b0846e2014-05-24 12:50:23 +0000669 bool isSIMDImmType10() const {
670 if (!isImm())
671 return false;
672 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
673 if (!MCE)
674 return false;
675 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
676 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000677
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000678 template<int N>
679 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000680 if (!isImm())
681 return false;
682 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
683 if (!MCE)
684 return true;
685 int64_t Val = MCE->getValue();
686 if (Val & 0x3)
687 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000688 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
689 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000690 }
691
692 bool
693 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
694 if (!isImm())
695 return false;
696
697 AArch64MCExpr::VariantKind ELFRefKind;
698 MCSymbolRefExpr::VariantKind DarwinRefKind;
699 int64_t Addend;
700 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
701 DarwinRefKind, Addend)) {
702 return false;
703 }
704 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
705 return false;
706
707 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
708 if (ELFRefKind == AllowedModifiers[i])
709 return Addend == 0;
710 }
711
712 return false;
713 }
714
715 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000716 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000717 }
718
719 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000720 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
721 AArch64MCExpr::VK_TPREL_G2,
722 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000723 }
724
725 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000726 return isMovWSymbol({
727 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000728 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
729 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000730 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000731 }
732
733 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000734 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
735 AArch64MCExpr::VK_TPREL_G0,
736 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000737 }
738
739 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000740 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000741 }
742
743 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000744 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000745 }
746
747 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000748 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
749 AArch64MCExpr::VK_TPREL_G1_NC,
750 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000751 }
752
753 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000754 return isMovWSymbol(
755 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
756 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000757 }
758
759 template<int RegWidth, int Shift>
760 bool isMOVZMovAlias() const {
761 if (!isImm()) return false;
762
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 uint64_t Value = CE->getValue();
766
Tim Northoverdaa1c012016-06-16 01:42:25 +0000767 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000768 }
769
770 template<int RegWidth, int Shift>
771 bool isMOVNMovAlias() const {
772 if (!isImm()) return false;
773
774 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
775 if (!CE) return false;
776 uint64_t Value = CE->getValue();
777
Tim Northoverdaa1c012016-06-16 01:42:25 +0000778 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000779 }
780
781 bool isFPImm() const { return Kind == k_FPImm; }
782 bool isBarrier() const { return Kind == k_Barrier; }
783 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000784
Tim Northover3b0846e2014-05-24 12:50:23 +0000785 bool isMRSSystemRegister() const {
786 if (!isSysReg()) return false;
787
Tim Northover7cd58932015-01-22 17:23:04 +0000788 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000789 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000790
Tim Northover3b0846e2014-05-24 12:50:23 +0000791 bool isMSRSystemRegister() const {
792 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000793 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000794 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000795
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000796 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000797 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000798 return (SysReg.PStateField == AArch64PState::PAN ||
799 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000800 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000801
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000802 bool isSystemPStateFieldWithImm0_15() const {
803 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000804 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000806
Tim Northover3b0846e2014-05-24 12:50:23 +0000807 bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
808 bool isVectorReg() const { return Kind == k_Register && Reg.isVector; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000809
Tim Northover3b0846e2014-05-24 12:50:23 +0000810 bool isVectorRegLo() const {
811 return Kind == k_Register && Reg.isVector &&
812 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
813 Reg.RegNum);
814 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000815
Tim Northover3b0846e2014-05-24 12:50:23 +0000816 bool isGPR32as64() const {
817 return Kind == k_Register && !Reg.isVector &&
818 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
819 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000820
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000821 bool isWSeqPair() const {
822 return Kind == k_Register && !Reg.isVector &&
823 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
824 Reg.RegNum);
825 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000826
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000827 bool isXSeqPair() const {
828 return Kind == k_Register && !Reg.isVector &&
829 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
830 Reg.RegNum);
831 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000832
833 bool isGPR64sp0() const {
834 return Kind == k_Register && !Reg.isVector &&
835 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
836 }
837
838 /// Is this a vector list with the type implicit (presumably attached to the
839 /// instruction itself)?
840 template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
841 return Kind == k_VectorList && VectorList.Count == NumRegs &&
842 !VectorList.ElementKind;
843 }
844
845 template <unsigned NumRegs, unsigned NumElements, char ElementKind>
846 bool isTypedVectorList() const {
847 if (Kind != k_VectorList)
848 return false;
849 if (VectorList.Count != NumRegs)
850 return false;
851 if (VectorList.ElementKind != ElementKind)
852 return false;
853 return VectorList.NumElements == NumElements;
854 }
855
856 bool isVectorIndex1() const {
857 return Kind == k_VectorIndex && VectorIndex.Val == 1;
858 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000859
Tim Northover3b0846e2014-05-24 12:50:23 +0000860 bool isVectorIndexB() const {
861 return Kind == k_VectorIndex && VectorIndex.Val < 16;
862 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000863
Tim Northover3b0846e2014-05-24 12:50:23 +0000864 bool isVectorIndexH() const {
865 return Kind == k_VectorIndex && VectorIndex.Val < 8;
866 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000867
Tim Northover3b0846e2014-05-24 12:50:23 +0000868 bool isVectorIndexS() const {
869 return Kind == k_VectorIndex && VectorIndex.Val < 4;
870 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000871
Tim Northover3b0846e2014-05-24 12:50:23 +0000872 bool isVectorIndexD() const {
873 return Kind == k_VectorIndex && VectorIndex.Val < 2;
874 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000875
Tim Northover3b0846e2014-05-24 12:50:23 +0000876 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000877
Tim Northover3b0846e2014-05-24 12:50:23 +0000878 bool isTokenEqual(StringRef Str) const {
879 return Kind == k_Token && getToken() == Str;
880 }
881 bool isSysCR() const { return Kind == k_SysCR; }
882 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000883 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000884 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
885 bool isShifter() const {
886 if (!isShiftExtend())
887 return false;
888
889 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
890 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
891 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
892 ST == AArch64_AM::MSL);
893 }
894 bool isExtend() const {
895 if (!isShiftExtend())
896 return false;
897
898 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
899 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
900 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
901 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
902 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
903 ET == AArch64_AM::LSL) &&
904 getShiftExtendAmount() <= 4;
905 }
906
907 bool isExtend64() const {
908 if (!isExtend())
909 return false;
910 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
911 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
912 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
913 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000914
Tim Northover3b0846e2014-05-24 12:50:23 +0000915 bool isExtendLSL64() const {
916 if (!isExtend())
917 return false;
918 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
919 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
920 ET == AArch64_AM::LSL) &&
921 getShiftExtendAmount() <= 4;
922 }
923
924 template<int Width> bool isMemXExtend() const {
925 if (!isExtend())
926 return false;
927 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
928 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
929 (getShiftExtendAmount() == Log2_32(Width / 8) ||
930 getShiftExtendAmount() == 0);
931 }
932
933 template<int Width> bool isMemWExtend() const {
934 if (!isExtend())
935 return false;
936 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
937 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
938 (getShiftExtendAmount() == Log2_32(Width / 8) ||
939 getShiftExtendAmount() == 0);
940 }
941
942 template <unsigned width>
943 bool isArithmeticShifter() const {
944 if (!isShifter())
945 return false;
946
947 // An arithmetic shifter is LSL, LSR, or ASR.
948 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
949 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
950 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
951 }
952
953 template <unsigned width>
954 bool isLogicalShifter() const {
955 if (!isShifter())
956 return false;
957
958 // A logical shifter is LSL, LSR, ASR or ROR.
959 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
960 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
961 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
962 getShiftExtendAmount() < width;
963 }
964
965 bool isMovImm32Shifter() const {
966 if (!isShifter())
967 return false;
968
969 // A MOVi shifter is LSL of 0, 16, 32, or 48.
970 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
971 if (ST != AArch64_AM::LSL)
972 return false;
973 uint64_t Val = getShiftExtendAmount();
974 return (Val == 0 || Val == 16);
975 }
976
977 bool isMovImm64Shifter() const {
978 if (!isShifter())
979 return false;
980
981 // A MOVi shifter is LSL of 0 or 16.
982 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
983 if (ST != AArch64_AM::LSL)
984 return false;
985 uint64_t Val = getShiftExtendAmount();
986 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
987 }
988
989 bool isLogicalVecShifter() const {
990 if (!isShifter())
991 return false;
992
993 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
994 unsigned Shift = getShiftExtendAmount();
995 return getShiftExtendType() == AArch64_AM::LSL &&
996 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
997 }
998
999 bool isLogicalVecHalfWordShifter() const {
1000 if (!isLogicalVecShifter())
1001 return false;
1002
1003 // A logical vector shifter is a left shift by 0 or 8.
1004 unsigned Shift = getShiftExtendAmount();
1005 return getShiftExtendType() == AArch64_AM::LSL &&
1006 (Shift == 0 || Shift == 8);
1007 }
1008
1009 bool isMoveVecShifter() const {
1010 if (!isShiftExtend())
1011 return false;
1012
1013 // A logical vector shifter is a left shift by 8 or 16.
1014 unsigned Shift = getShiftExtendAmount();
1015 return getShiftExtendType() == AArch64_AM::MSL &&
1016 (Shift == 8 || Shift == 16);
1017 }
1018
1019 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1020 // to LDUR/STUR when the offset is not legal for the former but is for
1021 // the latter. As such, in addition to checking for being a legal unscaled
1022 // address, also check that it is not a legal scaled address. This avoids
1023 // ambiguity in the matcher.
1024 template<int Width>
1025 bool isSImm9OffsetFB() const {
1026 return isSImm9() && !isUImm12Offset<Width / 8>();
1027 }
1028
1029 bool isAdrpLabel() const {
1030 // Validation was handled during parsing, so we just sanity check that
1031 // something didn't go haywire.
1032 if (!isImm())
1033 return false;
1034
1035 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1036 int64_t Val = CE->getValue();
1037 int64_t Min = - (4096 * (1LL << (21 - 1)));
1038 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1039 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1040 }
1041
1042 return true;
1043 }
1044
1045 bool isAdrLabel() const {
1046 // Validation was handled during parsing, so we just sanity check that
1047 // something didn't go haywire.
1048 if (!isImm())
1049 return false;
1050
1051 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1052 int64_t Val = CE->getValue();
1053 int64_t Min = - (1LL << (21 - 1));
1054 int64_t Max = ((1LL << (21 - 1)) - 1);
1055 return Val >= Min && Val <= Max;
1056 }
1057
1058 return true;
1059 }
1060
1061 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1062 // Add as immediates when possible. Null MCExpr = 0.
1063 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001064 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001065 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001066 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001067 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001068 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001069 }
1070
1071 void addRegOperands(MCInst &Inst, unsigned N) const {
1072 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001073 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001074 }
1075
1076 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1077 assert(N == 1 && "Invalid number of operands!");
1078 assert(
1079 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1080
1081 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1082 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1083 RI->getEncodingValue(getReg()));
1084
Jim Grosbache9119e42015-05-13 18:37:00 +00001085 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001086 }
1087
1088 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1089 assert(N == 1 && "Invalid number of operands!");
1090 assert(
1091 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001092 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001093 }
1094
1095 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1096 assert(N == 1 && "Invalid number of operands!");
1097 assert(
1098 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001099 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001100 }
1101
1102 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1103 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001104 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001105 }
1106
1107 template <unsigned NumRegs>
1108 void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1109 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001110 static const unsigned FirstRegs[] = { AArch64::D0,
1111 AArch64::D0_D1,
1112 AArch64::D0_D1_D2,
1113 AArch64::D0_D1_D2_D3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001114 unsigned FirstReg = FirstRegs[NumRegs - 1];
1115
1116 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001117 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001118 }
1119
1120 template <unsigned NumRegs>
1121 void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
Craig Topper26260942015-10-18 05:15:34 +00001123 static const unsigned FirstRegs[] = { AArch64::Q0,
1124 AArch64::Q0_Q1,
1125 AArch64::Q0_Q1_Q2,
1126 AArch64::Q0_Q1_Q2_Q3 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001127 unsigned FirstReg = FirstRegs[NumRegs - 1];
1128
1129 Inst.addOperand(
Jim Grosbache9119e42015-05-13 18:37:00 +00001130 MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001131 }
1132
1133 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1134 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001135 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001136 }
1137
1138 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1139 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001140 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001141 }
1142
1143 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001145 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001146 }
1147
1148 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1149 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001150 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001151 }
1152
1153 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1154 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001155 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001156 }
1157
1158 void addImmOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 1 && "Invalid number of operands!");
1160 // If this is a pageoff symrefexpr with an addend, adjust the addend
1161 // to be only the page-offset portion. Otherwise, just add the expr
1162 // as-is.
1163 addExpr(Inst, getImm());
1164 }
1165
1166 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1167 assert(N == 2 && "Invalid number of operands!");
1168 if (isShiftedImm()) {
1169 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001170 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001171 } else {
1172 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001173 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001174 }
1175 }
1176
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001177 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1178 assert(N == 2 && "Invalid number of operands!");
1179
1180 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1181 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1182 int64_t Val = -CE->getValue();
1183 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1184
1185 Inst.addOperand(MCOperand::createImm(Val));
1186 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1187 }
1188
Tim Northover3b0846e2014-05-24 12:50:23 +00001189 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001191 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001192 }
1193
1194 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!");
1196 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1197 if (!MCE)
1198 addExpr(Inst, getImm());
1199 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001200 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001201 }
1202
1203 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1204 addImmOperands(Inst, N);
1205 }
1206
1207 template<int Scale>
1208 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1209 assert(N == 1 && "Invalid number of operands!");
1210 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1211
1212 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001213 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001214 return;
1215 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001216 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001217 }
1218
1219 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1220 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001221 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001222 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001223 }
1224
Sam Parker6d42de72017-08-11 13:14:00 +00001225 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1226 assert(N == 1 && "Invalid number of operands!");
1227 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1228 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1229 }
1230
Tim Northover3b0846e2014-05-24 12:50:23 +00001231 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001233 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001234 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001235 }
1236
1237 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1238 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001239 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001240 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001241 }
1242
1243 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1244 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001245 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001246 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001247 }
1248
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001249 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
1251 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1252 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1253 }
1254
Tim Northover3b0846e2014-05-24 12:50:23 +00001255 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001257 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001258 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001259 }
1260
1261 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001263 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001264 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001265 }
1266
1267 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1268 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001269 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001270 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001271 }
1272
1273 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1274 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001275 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001276 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001277 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001278 }
1279
1280 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1281 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001282 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001283 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001284 }
1285
1286 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1287 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001288 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001289 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001290 }
1291
1292 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1293 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001294 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001295 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001296 }
1297
1298 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1299 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001300 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001301 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001302 }
1303
1304 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1305 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001306 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001307 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001308 }
1309
1310 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1311 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001312 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001313 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001314 }
1315
1316 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1317 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001318 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001319 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001320 }
1321
1322 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1323 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001324 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001325 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001326 }
1327
1328 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001330 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001331 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001332 }
1333
1334 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1335 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001336 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001337 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
1340 void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001342 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +00001343 uint64_t encoding =
1344 AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001345 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001346 }
1347
1348 void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001350 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001351 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001352 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001353 }
1354
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001355 void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1356 assert(N == 1 && "Invalid number of operands!");
1357 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1358 int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1359 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001360 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001361 }
1362
1363 void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
1365 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1366 uint64_t encoding =
1367 AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Jim Grosbache9119e42015-05-13 18:37:00 +00001368 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001369 }
1370
Tim Northover3b0846e2014-05-24 12:50:23 +00001371 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1372 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001373 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001375 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001376 }
1377
1378 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1379 // Branch operands don't encode the low bits, so shift them off
1380 // here. If it's a label, however, just put it on directly as there's
1381 // not enough information now to do anything.
1382 assert(N == 1 && "Invalid number of operands!");
1383 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1384 if (!MCE) {
1385 addExpr(Inst, getImm());
1386 return;
1387 }
1388 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001389 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 }
1391
1392 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1393 // Branch operands don't encode the low bits, so shift them off
1394 // here. If it's a label, however, just put it on directly as there's
1395 // not enough information now to do anything.
1396 assert(N == 1 && "Invalid number of operands!");
1397 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1398 if (!MCE) {
1399 addExpr(Inst, getImm());
1400 return;
1401 }
1402 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001403 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 }
1405
1406 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1407 // Branch operands don't encode the low bits, so shift them off
1408 // here. If it's a label, however, just put it on directly as there's
1409 // not enough information now to do anything.
1410 assert(N == 1 && "Invalid number of operands!");
1411 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1412 if (!MCE) {
1413 addExpr(Inst, getImm());
1414 return;
1415 }
1416 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001417 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001418 }
1419
1420 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1421 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001422 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001423 }
1424
1425 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001427 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001428 }
1429
1430 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 1 && "Invalid number of operands!");
1432
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438
Jim Grosbache9119e42015-05-13 18:37:00 +00001439 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001440 }
1441
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001442 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1443 assert(N == 1 && "Invalid number of operands!");
1444
1445 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1446 }
1447
1448 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001449 assert(N == 1 && "Invalid number of operands!");
1450
Jim Grosbache9119e42015-05-13 18:37:00 +00001451 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001452 }
1453
1454 void addSysCROperands(MCInst &Inst, unsigned N) const {
1455 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001456 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001457 }
1458
1459 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1460 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001461 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001462 }
1463
Oliver Stannarda34e4702015-12-01 10:48:51 +00001464 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1465 assert(N == 1 && "Invalid number of operands!");
1466 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1467 }
1468
Tim Northover3b0846e2014-05-24 12:50:23 +00001469 void addShifterOperands(MCInst &Inst, unsigned N) const {
1470 assert(N == 1 && "Invalid number of operands!");
1471 unsigned Imm =
1472 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001473 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001474 }
1475
1476 void addExtendOperands(MCInst &Inst, unsigned N) const {
1477 assert(N == 1 && "Invalid number of operands!");
1478 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1479 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1480 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
1484 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
1486 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1487 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1488 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001489 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001490 }
1491
1492 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1493 assert(N == 2 && "Invalid number of operands!");
1494 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1495 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001496 Inst.addOperand(MCOperand::createImm(IsSigned));
1497 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001498 }
1499
1500 // For 8-bit load/store instructions with a register offset, both the
1501 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1502 // they're disambiguated by whether the shift was explicit or implicit rather
1503 // than its size.
1504 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1505 assert(N == 2 && "Invalid number of operands!");
1506 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1507 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001508 Inst.addOperand(MCOperand::createImm(IsSigned));
1509 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001510 }
1511
1512 template<int Shift>
1513 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1514 assert(N == 1 && "Invalid number of operands!");
1515
1516 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1517 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001518 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001519 }
1520
1521 template<int Shift>
1522 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524
1525 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1526 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001527 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
1530 void print(raw_ostream &OS) const override;
1531
David Blaikie960ea3f2014-06-08 16:18:35 +00001532 static std::unique_ptr<AArch64Operand>
1533 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1534 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001535 Op->Tok.Data = Str.data();
1536 Op->Tok.Length = Str.size();
1537 Op->Tok.IsSuffix = IsSuffix;
1538 Op->StartLoc = S;
1539 Op->EndLoc = S;
1540 return Op;
1541 }
1542
David Blaikie960ea3f2014-06-08 16:18:35 +00001543 static std::unique_ptr<AArch64Operand>
1544 CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
1545 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001546 Op->Reg.RegNum = RegNum;
1547 Op->Reg.isVector = isVector;
1548 Op->StartLoc = S;
1549 Op->EndLoc = E;
1550 return Op;
1551 }
1552
David Blaikie960ea3f2014-06-08 16:18:35 +00001553 static std::unique_ptr<AArch64Operand>
1554 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1555 char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1556 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 Op->VectorList.RegNum = RegNum;
1558 Op->VectorList.Count = Count;
1559 Op->VectorList.NumElements = NumElements;
1560 Op->VectorList.ElementKind = ElementKind;
1561 Op->StartLoc = S;
1562 Op->EndLoc = E;
1563 return Op;
1564 }
1565
David Blaikie960ea3f2014-06-08 16:18:35 +00001566 static std::unique_ptr<AArch64Operand>
1567 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1568 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001569 Op->VectorIndex.Val = Idx;
1570 Op->StartLoc = S;
1571 Op->EndLoc = E;
1572 return Op;
1573 }
1574
David Blaikie960ea3f2014-06-08 16:18:35 +00001575 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1576 SMLoc E, MCContext &Ctx) {
1577 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001578 Op->Imm.Val = Val;
1579 Op->StartLoc = S;
1580 Op->EndLoc = E;
1581 return Op;
1582 }
1583
David Blaikie960ea3f2014-06-08 16:18:35 +00001584 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1585 unsigned ShiftAmount,
1586 SMLoc S, SMLoc E,
1587 MCContext &Ctx) {
1588 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001589 Op->ShiftedImm .Val = Val;
1590 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1591 Op->StartLoc = S;
1592 Op->EndLoc = E;
1593 return Op;
1594 }
1595
David Blaikie960ea3f2014-06-08 16:18:35 +00001596 static std::unique_ptr<AArch64Operand>
1597 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1598 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001599 Op->CondCode.Code = Code;
1600 Op->StartLoc = S;
1601 Op->EndLoc = E;
1602 return Op;
1603 }
1604
David Blaikie960ea3f2014-06-08 16:18:35 +00001605 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1606 MCContext &Ctx) {
1607 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001608 Op->FPImm.Val = Val;
1609 Op->StartLoc = S;
1610 Op->EndLoc = S;
1611 return Op;
1612 }
1613
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001614 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1615 StringRef Str,
1616 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001617 MCContext &Ctx) {
1618 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001619 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001620 Op->Barrier.Data = Str.data();
1621 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001622 Op->StartLoc = S;
1623 Op->EndLoc = S;
1624 return Op;
1625 }
1626
Tim Northover7cd58932015-01-22 17:23:04 +00001627 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1628 uint32_t MRSReg,
1629 uint32_t MSRReg,
1630 uint32_t PStateField,
1631 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001632 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001633 Op->SysReg.Data = Str.data();
1634 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001635 Op->SysReg.MRSReg = MRSReg;
1636 Op->SysReg.MSRReg = MSRReg;
1637 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001638 Op->StartLoc = S;
1639 Op->EndLoc = S;
1640 return Op;
1641 }
1642
David Blaikie960ea3f2014-06-08 16:18:35 +00001643 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1644 SMLoc E, MCContext &Ctx) {
1645 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001646 Op->SysCRImm.Val = Val;
1647 Op->StartLoc = S;
1648 Op->EndLoc = E;
1649 return Op;
1650 }
1651
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001652 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1653 StringRef Str,
1654 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001655 MCContext &Ctx) {
1656 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001657 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001658 Op->Barrier.Data = Str.data();
1659 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001660 Op->StartLoc = S;
1661 Op->EndLoc = S;
1662 return Op;
1663 }
1664
Oliver Stannarda34e4702015-12-01 10:48:51 +00001665 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1666 StringRef Str,
1667 SMLoc S,
1668 MCContext &Ctx) {
1669 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1670 Op->PSBHint.Val = Val;
1671 Op->PSBHint.Data = Str.data();
1672 Op->PSBHint.Length = Str.size();
1673 Op->StartLoc = S;
1674 Op->EndLoc = S;
1675 return Op;
1676 }
1677
David Blaikie960ea3f2014-06-08 16:18:35 +00001678 static std::unique_ptr<AArch64Operand>
1679 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1680 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1681 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001682 Op->ShiftExtend.Type = ShOp;
1683 Op->ShiftExtend.Amount = Val;
1684 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1685 Op->StartLoc = S;
1686 Op->EndLoc = E;
1687 return Op;
1688 }
1689};
1690
1691} // end anonymous namespace.
1692
1693void AArch64Operand::print(raw_ostream &OS) const {
1694 switch (Kind) {
1695 case k_FPImm:
1696 OS << "<fpimm " << getFPImm() << "("
1697 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1698 break;
1699 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001700 StringRef Name = getBarrierName();
1701 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001702 OS << "<barrier " << Name << ">";
1703 else
1704 OS << "<barrier invalid #" << getBarrier() << ">";
1705 break;
1706 }
1707 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001708 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001709 break;
1710 case k_ShiftedImm: {
1711 unsigned Shift = getShiftedImmShift();
1712 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001713 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001714 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1715 break;
1716 }
1717 case k_CondCode:
1718 OS << "<condcode " << getCondCode() << ">";
1719 break;
1720 case k_Register:
1721 OS << "<register " << getReg() << ">";
1722 break;
1723 case k_VectorList: {
1724 OS << "<vectorlist ";
1725 unsigned Reg = getVectorListStart();
1726 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1727 OS << Reg + i << " ";
1728 OS << ">";
1729 break;
1730 }
1731 case k_VectorIndex:
1732 OS << "<vectorindex " << getVectorIndex() << ">";
1733 break;
1734 case k_SysReg:
1735 OS << "<sysreg: " << getSysReg() << '>';
1736 break;
1737 case k_Token:
1738 OS << "'" << getToken() << "'";
1739 break;
1740 case k_SysCR:
1741 OS << "c" << getSysCR();
1742 break;
1743 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001744 StringRef Name = getPrefetchName();
1745 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001746 OS << "<prfop " << Name << ">";
1747 else
1748 OS << "<prfop invalid #" << getPrefetch() << ">";
1749 break;
1750 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001751 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001752 OS << getPSBHintName();
1753 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001754 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001755 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1756 << getShiftExtendAmount();
1757 if (!hasShiftExtendAmount())
1758 OS << "<imp>";
1759 OS << '>';
1760 break;
1761 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001762}
1763
1764/// @name Auto-generated Match Functions
1765/// {
1766
1767static unsigned MatchRegisterName(StringRef Name);
1768
1769/// }
1770
1771static unsigned matchVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001772 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001773 .Case("v0", AArch64::Q0)
1774 .Case("v1", AArch64::Q1)
1775 .Case("v2", AArch64::Q2)
1776 .Case("v3", AArch64::Q3)
1777 .Case("v4", AArch64::Q4)
1778 .Case("v5", AArch64::Q5)
1779 .Case("v6", AArch64::Q6)
1780 .Case("v7", AArch64::Q7)
1781 .Case("v8", AArch64::Q8)
1782 .Case("v9", AArch64::Q9)
1783 .Case("v10", AArch64::Q10)
1784 .Case("v11", AArch64::Q11)
1785 .Case("v12", AArch64::Q12)
1786 .Case("v13", AArch64::Q13)
1787 .Case("v14", AArch64::Q14)
1788 .Case("v15", AArch64::Q15)
1789 .Case("v16", AArch64::Q16)
1790 .Case("v17", AArch64::Q17)
1791 .Case("v18", AArch64::Q18)
1792 .Case("v19", AArch64::Q19)
1793 .Case("v20", AArch64::Q20)
1794 .Case("v21", AArch64::Q21)
1795 .Case("v22", AArch64::Q22)
1796 .Case("v23", AArch64::Q23)
1797 .Case("v24", AArch64::Q24)
1798 .Case("v25", AArch64::Q25)
1799 .Case("v26", AArch64::Q26)
1800 .Case("v27", AArch64::Q27)
1801 .Case("v28", AArch64::Q28)
1802 .Case("v29", AArch64::Q29)
1803 .Case("v30", AArch64::Q30)
1804 .Case("v31", AArch64::Q31)
1805 .Default(0);
1806}
1807
1808static bool isValidVectorKind(StringRef Name) {
1809 return StringSwitch<bool>(Name.lower())
1810 .Case(".8b", true)
1811 .Case(".16b", true)
1812 .Case(".4h", true)
1813 .Case(".8h", true)
1814 .Case(".2s", true)
1815 .Case(".4s", true)
1816 .Case(".1d", true)
1817 .Case(".2d", true)
1818 .Case(".1q", true)
1819 // Accept the width neutral ones, too, for verbose syntax. If those
1820 // aren't used in the right places, the token operand won't match so
1821 // all will work out.
1822 .Case(".b", true)
1823 .Case(".h", true)
1824 .Case(".s", true)
1825 .Case(".d", true)
Oliver Stannarde4c3d212015-12-08 12:16:10 +00001826 // Needed for fp16 scalar pairwise reductions
1827 .Case(".2h", true)
Sjoerd Meijer79876332017-08-09 14:59:54 +00001828 // another special case for the ARMv8.2a dot product operand
1829 .Case(".4b", true)
Tim Northover3b0846e2014-05-24 12:50:23 +00001830 .Default(false);
1831}
1832
1833static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1834 char &ElementKind) {
1835 assert(isValidVectorKind(Name));
1836
1837 ElementKind = Name.lower()[Name.size() - 1];
1838 NumElements = 0;
1839
1840 if (Name.size() == 2)
1841 return;
1842
1843 // Parse the lane count
1844 Name = Name.drop_front();
1845 while (isdigit(Name.front())) {
1846 NumElements = 10 * NumElements + (Name.front() - '0');
1847 Name = Name.drop_front();
1848 }
1849}
1850
1851bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1852 SMLoc &EndLoc) {
1853 StartLoc = getLoc();
1854 RegNo = tryParseRegister();
1855 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1856 return (RegNo == (unsigned)-1);
1857}
1858
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001859// Matches a register name or register alias previously defined by '.req'
1860unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
1861 bool isVector) {
1862 unsigned RegNum = isVector ? matchVectorRegName(Name)
1863 : MatchRegisterName(Name);
1864
1865 if (RegNum == 0) {
1866 // Check for aliases registered via .req. Canonicalize to lower case.
1867 // That's more consistent since register names are case insensitive, and
1868 // it's how the original entry was passed in from MC/MCParser/AsmParser.
1869 auto Entry = RegisterReqs.find(Name.lower());
1870 if (Entry == RegisterReqs.end())
1871 return 0;
1872 // set RegNum if the match is the right kind of register
1873 if (isVector == Entry->getValue().first)
1874 RegNum = Entry->getValue().second;
1875 }
1876 return RegNum;
1877}
1878
Tim Northover3b0846e2014-05-24 12:50:23 +00001879/// tryParseRegister - Try to parse a register name. The token must be an
1880/// Identifier when called, and if it is a register name the token is eaten and
1881/// the register is added to the operand list.
1882int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00001883 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001884 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00001885 if (Tok.isNot(AsmToken::Identifier))
1886 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00001887
1888 std::string lowerCase = Tok.getString().lower();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001889 unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
Tim Northover3b0846e2014-05-24 12:50:23 +00001890 // Also handle a few aliases of registers.
1891 if (RegNum == 0)
1892 RegNum = StringSwitch<unsigned>(lowerCase)
1893 .Case("fp", AArch64::FP)
1894 .Case("lr", AArch64::LR)
1895 .Case("x31", AArch64::XZR)
1896 .Case("w31", AArch64::WZR)
1897 .Default(0);
1898
1899 if (RegNum == 0)
1900 return -1;
1901
1902 Parser.Lex(); // Eat identifier token.
1903 return RegNum;
1904}
1905
1906/// tryMatchVectorRegister - Try to parse a vector register name with optional
1907/// kind specifier. If it is a register specifier, eat the token and return it.
1908int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001909 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001910 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1911 TokError("vector register expected");
1912 return -1;
1913 }
1914
1915 StringRef Name = Parser.getTok().getString();
1916 // If there is a kind specifier, it's separated from the register name by
1917 // a '.'.
1918 size_t Start = 0, Next = Name.find('.');
1919 StringRef Head = Name.slice(Start, Next);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001920 unsigned RegNum = matchRegisterNameAlias(Head, true);
1921
Tim Northover3b0846e2014-05-24 12:50:23 +00001922 if (RegNum) {
1923 if (Next != StringRef::npos) {
1924 Kind = Name.slice(Next, StringRef::npos);
1925 if (!isValidVectorKind(Kind)) {
1926 TokError("invalid vector kind qualifier");
1927 return -1;
1928 }
1929 }
1930 Parser.Lex(); // Eat the register token.
1931 return RegNum;
1932 }
1933
1934 if (expected)
1935 TokError("vector register expected");
1936 return -1;
1937}
1938
1939/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00001940OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001941AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001942 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001943 SMLoc S = getLoc();
1944
1945 if (Parser.getTok().isNot(AsmToken::Identifier)) {
1946 Error(S, "Expected cN operand where 0 <= N <= 15");
1947 return MatchOperand_ParseFail;
1948 }
1949
1950 StringRef Tok = Parser.getTok().getIdentifier();
1951 if (Tok[0] != 'c' && Tok[0] != 'C') {
1952 Error(S, "Expected cN operand where 0 <= N <= 15");
1953 return MatchOperand_ParseFail;
1954 }
1955
1956 uint32_t CRNum;
1957 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
1958 if (BadNum || CRNum > 15) {
1959 Error(S, "Expected cN operand where 0 <= N <= 15");
1960 return MatchOperand_ParseFail;
1961 }
1962
1963 Parser.Lex(); // Eat identifier token.
1964 Operands.push_back(
1965 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
1966 return MatchOperand_Success;
1967}
1968
1969/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00001970OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00001971AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00001972 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00001973 SMLoc S = getLoc();
1974 const AsmToken &Tok = Parser.getTok();
1975 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00001976 // Eat optional hash.
1977 if (parseOptionalToken(AsmToken::Hash) ||
1978 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001979 const MCExpr *ImmVal;
1980 if (getParser().parseExpression(ImmVal))
1981 return MatchOperand_ParseFail;
1982
1983 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1984 if (!MCE) {
1985 TokError("immediate value expected for prefetch operand");
1986 return MatchOperand_ParseFail;
1987 }
1988 unsigned prfop = MCE->getValue();
1989 if (prfop > 31) {
1990 TokError("prefetch operand out of range, [0,31] expected");
1991 return MatchOperand_ParseFail;
1992 }
1993
Tim Northovere6ae6762016-07-05 21:23:04 +00001994 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
1995 Operands.push_back(AArch64Operand::CreatePrefetch(
1996 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001997 return MatchOperand_Success;
1998 }
1999
2000 if (Tok.isNot(AsmToken::Identifier)) {
2001 TokError("pre-fetch hint expected");
2002 return MatchOperand_ParseFail;
2003 }
2004
Tim Northovere6ae6762016-07-05 21:23:04 +00002005 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2006 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002007 TokError("pre-fetch hint expected");
2008 return MatchOperand_ParseFail;
2009 }
2010
2011 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002012 Operands.push_back(AArch64Operand::CreatePrefetch(
2013 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002014 return MatchOperand_Success;
2015}
2016
Oliver Stannarda34e4702015-12-01 10:48:51 +00002017/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002018OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002019AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2020 MCAsmParser &Parser = getParser();
2021 SMLoc S = getLoc();
2022 const AsmToken &Tok = Parser.getTok();
2023 if (Tok.isNot(AsmToken::Identifier)) {
2024 TokError("invalid operand for instruction");
2025 return MatchOperand_ParseFail;
2026 }
2027
Tim Northovere6ae6762016-07-05 21:23:04 +00002028 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2029 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002030 TokError("invalid operand for instruction");
2031 return MatchOperand_ParseFail;
2032 }
2033
2034 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002035 Operands.push_back(AArch64Operand::CreatePSBHint(
2036 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002037 return MatchOperand_Success;
2038}
2039
Tim Northover3b0846e2014-05-24 12:50:23 +00002040/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2041/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002042OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002043AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002044 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002045 SMLoc S = getLoc();
2046 const MCExpr *Expr;
2047
2048 if (Parser.getTok().is(AsmToken::Hash)) {
2049 Parser.Lex(); // Eat hash token.
2050 }
2051
2052 if (parseSymbolicImmVal(Expr))
2053 return MatchOperand_ParseFail;
2054
2055 AArch64MCExpr::VariantKind ELFRefKind;
2056 MCSymbolRefExpr::VariantKind DarwinRefKind;
2057 int64_t Addend;
2058 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2059 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2060 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2061 // No modifier was specified at all; this is the syntax for an ELF basic
2062 // ADRP relocation (unfortunately).
2063 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002064 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002065 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2066 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2067 Addend != 0) {
2068 Error(S, "gotpage label reference not allowed an addend");
2069 return MatchOperand_ParseFail;
2070 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2071 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2072 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2073 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2074 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2075 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2076 // The operand must be an @page or @gotpage qualified symbolref.
2077 Error(S, "page or gotpage label reference expected");
2078 return MatchOperand_ParseFail;
2079 }
2080 }
2081
2082 // We have either a label reference possibly with addend or an immediate. The
2083 // addend is a raw value here. The linker will adjust it to only reference the
2084 // page.
2085 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2086 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2087
2088 return MatchOperand_Success;
2089}
2090
2091/// tryParseAdrLabel - Parse and validate a source label for the ADR
2092/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002093OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002094AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2095 SMLoc S = getLoc();
2096 const MCExpr *Expr;
2097
Nirav Davee833c6c2016-11-08 18:31:04 +00002098 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002099 if (getParser().parseExpression(Expr))
2100 return MatchOperand_ParseFail;
2101
2102 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2103 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2104
2105 return MatchOperand_Success;
2106}
2107
2108/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002109OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002110AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002111 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002112 SMLoc S = getLoc();
2113
Nirav Davee833c6c2016-11-08 18:31:04 +00002114 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002115
2116 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002117 bool isNegative = parseOptionalToken(AsmToken::Minus);
2118
Tim Northover3b0846e2014-05-24 12:50:23 +00002119 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002120 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002121 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002122 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002123 Val = Tok.getIntVal();
2124 if (Val > 255 || Val < 0) {
2125 TokError("encoded floating point value out of range");
2126 return MatchOperand_ParseFail;
2127 }
2128 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002129 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002130 if (isNegative)
2131 RealVal.changeSign();
2132
Tim Northover3b0846e2014-05-24 12:50:23 +00002133 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002134 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002135
John Brawn5ca5daa2017-04-20 10:13:54 +00002136 // Check for out of range values. As an exception we let Zero through,
2137 // but as tokens instead of an FPImm so that it can be matched by the
2138 // appropriate alias if one exists.
2139 if (RealVal.isPosZero()) {
2140 Parser.Lex(); // Eat the token.
2141 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2142 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2143 return MatchOperand_Success;
2144 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002145 TokError("expected compatible register or floating-point constant");
2146 return MatchOperand_ParseFail;
2147 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002148 }
2149 Parser.Lex(); // Eat the token.
2150 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2151 return MatchOperand_Success;
2152 }
2153
2154 if (!Hash)
2155 return MatchOperand_NoMatch;
2156
2157 TokError("invalid floating point immediate");
2158 return MatchOperand_ParseFail;
2159}
2160
2161/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002162OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002163AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002164 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002165 SMLoc S = getLoc();
2166
2167 if (Parser.getTok().is(AsmToken::Hash))
2168 Parser.Lex(); // Eat '#'
2169 else if (Parser.getTok().isNot(AsmToken::Integer))
2170 // Operand should start from # or should be integer, emit error otherwise.
2171 return MatchOperand_NoMatch;
2172
2173 const MCExpr *Imm;
2174 if (parseSymbolicImmVal(Imm))
2175 return MatchOperand_ParseFail;
2176 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2177 uint64_t ShiftAmount = 0;
2178 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2179 if (MCE) {
2180 int64_t Val = MCE->getValue();
2181 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002182 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002183 ShiftAmount = 12;
2184 }
2185 }
2186 SMLoc E = Parser.getTok().getLoc();
2187 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2188 getContext()));
2189 return MatchOperand_Success;
2190 }
2191
2192 // Eat ','
2193 Parser.Lex();
2194
2195 // The optional operand must be "lsl #N" where N is non-negative.
2196 if (!Parser.getTok().is(AsmToken::Identifier) ||
2197 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2198 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2199 return MatchOperand_ParseFail;
2200 }
2201
2202 // Eat 'lsl'
2203 Parser.Lex();
2204
Nirav Davee833c6c2016-11-08 18:31:04 +00002205 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002206
2207 if (Parser.getTok().isNot(AsmToken::Integer)) {
2208 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2209 return MatchOperand_ParseFail;
2210 }
2211
2212 int64_t ShiftAmount = Parser.getTok().getIntVal();
2213
2214 if (ShiftAmount < 0) {
2215 Error(Parser.getTok().getLoc(), "positive shift amount required");
2216 return MatchOperand_ParseFail;
2217 }
2218 Parser.Lex(); // Eat the number
2219
2220 SMLoc E = Parser.getTok().getLoc();
2221 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2222 S, E, getContext()));
2223 return MatchOperand_Success;
2224}
2225
2226/// parseCondCodeString - Parse a Condition Code string.
2227AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2228 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2229 .Case("eq", AArch64CC::EQ)
2230 .Case("ne", AArch64CC::NE)
2231 .Case("cs", AArch64CC::HS)
2232 .Case("hs", AArch64CC::HS)
2233 .Case("cc", AArch64CC::LO)
2234 .Case("lo", AArch64CC::LO)
2235 .Case("mi", AArch64CC::MI)
2236 .Case("pl", AArch64CC::PL)
2237 .Case("vs", AArch64CC::VS)
2238 .Case("vc", AArch64CC::VC)
2239 .Case("hi", AArch64CC::HI)
2240 .Case("ls", AArch64CC::LS)
2241 .Case("ge", AArch64CC::GE)
2242 .Case("lt", AArch64CC::LT)
2243 .Case("gt", AArch64CC::GT)
2244 .Case("le", AArch64CC::LE)
2245 .Case("al", AArch64CC::AL)
2246 .Case("nv", AArch64CC::NV)
2247 .Default(AArch64CC::Invalid);
2248 return CC;
2249}
2250
2251/// parseCondCode - Parse a Condition Code operand.
2252bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2253 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002254 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002255 SMLoc S = getLoc();
2256 const AsmToken &Tok = Parser.getTok();
2257 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2258
2259 StringRef Cond = Tok.getString();
2260 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2261 if (CC == AArch64CC::Invalid)
2262 return TokError("invalid condition code");
2263 Parser.Lex(); // Eat identifier token.
2264
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002265 if (invertCondCode) {
2266 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2267 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002268 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002269 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002270
2271 Operands.push_back(
2272 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2273 return false;
2274}
2275
2276/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2277/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002278OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002279AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002280 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002281 const AsmToken &Tok = Parser.getTok();
2282 std::string LowerID = Tok.getString().lower();
2283 AArch64_AM::ShiftExtendType ShOp =
2284 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2285 .Case("lsl", AArch64_AM::LSL)
2286 .Case("lsr", AArch64_AM::LSR)
2287 .Case("asr", AArch64_AM::ASR)
2288 .Case("ror", AArch64_AM::ROR)
2289 .Case("msl", AArch64_AM::MSL)
2290 .Case("uxtb", AArch64_AM::UXTB)
2291 .Case("uxth", AArch64_AM::UXTH)
2292 .Case("uxtw", AArch64_AM::UXTW)
2293 .Case("uxtx", AArch64_AM::UXTX)
2294 .Case("sxtb", AArch64_AM::SXTB)
2295 .Case("sxth", AArch64_AM::SXTH)
2296 .Case("sxtw", AArch64_AM::SXTW)
2297 .Case("sxtx", AArch64_AM::SXTX)
2298 .Default(AArch64_AM::InvalidShiftExtend);
2299
2300 if (ShOp == AArch64_AM::InvalidShiftExtend)
2301 return MatchOperand_NoMatch;
2302
2303 SMLoc S = Tok.getLoc();
2304 Parser.Lex();
2305
Nirav Davee833c6c2016-11-08 18:31:04 +00002306 bool Hash = parseOptionalToken(AsmToken::Hash);
2307
Tim Northover3b0846e2014-05-24 12:50:23 +00002308 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2309 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2310 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2311 ShOp == AArch64_AM::MSL) {
2312 // We expect a number here.
2313 TokError("expected #imm after shift specifier");
2314 return MatchOperand_ParseFail;
2315 }
2316
Chad Rosier2ff37b82016-12-27 16:58:09 +00002317 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002318 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2319 Operands.push_back(
2320 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2321 return MatchOperand_Success;
2322 }
2323
Chad Rosier2ff37b82016-12-27 16:58:09 +00002324 // Make sure we do actually have a number, identifier or a parenthesized
2325 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002326 SMLoc E = Parser.getTok().getLoc();
2327 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002328 !Parser.getTok().is(AsmToken::LParen) &&
2329 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002330 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002331 return MatchOperand_ParseFail;
2332 }
2333
2334 const MCExpr *ImmVal;
2335 if (getParser().parseExpression(ImmVal))
2336 return MatchOperand_ParseFail;
2337
2338 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2339 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002340 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002341 return MatchOperand_ParseFail;
2342 }
2343
Jim Grosbach57fd2622014-09-23 22:16:02 +00002344 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002345 Operands.push_back(AArch64Operand::CreateShiftExtend(
2346 ShOp, MCE->getValue(), true, S, E, getContext()));
2347 return MatchOperand_Success;
2348}
2349
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002350static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2351 if (FBS[AArch64::HasV8_1aOps])
2352 Str += "ARMv8.1a";
2353 else if (FBS[AArch64::HasV8_2aOps])
2354 Str += "ARMv8.2a";
2355 else
2356 Str += "(unknown)";
2357}
2358
2359void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2360 SMLoc S) {
2361 const uint16_t Op2 = Encoding & 7;
2362 const uint16_t Cm = (Encoding & 0x78) >> 3;
2363 const uint16_t Cn = (Encoding & 0x780) >> 7;
2364 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2365
2366 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2367
2368 Operands.push_back(
2369 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2370 Operands.push_back(
2371 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2372 Operands.push_back(
2373 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2374 Expr = MCConstantExpr::create(Op2, getContext());
2375 Operands.push_back(
2376 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2377}
2378
Tim Northover3b0846e2014-05-24 12:50:23 +00002379/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2380/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2381bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2382 OperandVector &Operands) {
2383 if (Name.find('.') != StringRef::npos)
2384 return TokError("invalid operand");
2385
2386 Mnemonic = Name;
2387 Operands.push_back(
2388 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2389
Rafael Espindola961d4692014-11-11 05:18:41 +00002390 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002391 const AsmToken &Tok = Parser.getTok();
2392 StringRef Op = Tok.getString();
2393 SMLoc S = Tok.getLoc();
2394
Tim Northover3b0846e2014-05-24 12:50:23 +00002395 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002396 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2397 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002398 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002399 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2400 std::string Str("IC " + std::string(IC->Name) + " requires ");
2401 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2402 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002403 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002404 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002405 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002406 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2407 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002408 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002409 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2410 std::string Str("DC " + std::string(DC->Name) + " requires ");
2411 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2412 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002413 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002414 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002415 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002416 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2417 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002418 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002419 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2420 std::string Str("AT " + std::string(AT->Name) + " requires ");
2421 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2422 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002423 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002424 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002425 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002426 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2427 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002428 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002429 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2430 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2431 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2432 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002433 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002434 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002435 }
2436
Tim Northover3b0846e2014-05-24 12:50:23 +00002437 Parser.Lex(); // Eat operand.
2438
2439 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2440 bool HasRegister = false;
2441
2442 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002443 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002444 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2445 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002446 HasRegister = true;
2447 }
2448
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002449 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002450 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002451 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002452 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002453
Nirav Davee833c6c2016-11-08 18:31:04 +00002454 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2455 return true;
2456
Tim Northover3b0846e2014-05-24 12:50:23 +00002457 return false;
2458}
2459
Alex Bradbury58eba092016-11-01 16:32:05 +00002460OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002461AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002462 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002463 const AsmToken &Tok = Parser.getTok();
2464
2465 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002466 if (parseOptionalToken(AsmToken::Hash) ||
2467 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002468 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002469 const MCExpr *ImmVal;
2470 SMLoc ExprLoc = getLoc();
2471 if (getParser().parseExpression(ImmVal))
2472 return MatchOperand_ParseFail;
2473 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2474 if (!MCE) {
2475 Error(ExprLoc, "immediate value expected for barrier operand");
2476 return MatchOperand_ParseFail;
2477 }
2478 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2479 Error(ExprLoc, "barrier operand out of range");
2480 return MatchOperand_ParseFail;
2481 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002482 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2483 Operands.push_back(AArch64Operand::CreateBarrier(
2484 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002485 return MatchOperand_Success;
2486 }
2487
2488 if (Tok.isNot(AsmToken::Identifier)) {
2489 TokError("invalid operand for instruction");
2490 return MatchOperand_ParseFail;
2491 }
2492
Tim Northover3b0846e2014-05-24 12:50:23 +00002493 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002494 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2495 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002496 TokError("'sy' or #imm operand expected");
2497 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002498 } else if (!DB) {
2499 TokError("invalid barrier option name");
2500 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002501 }
2502
Tim Northovere6ae6762016-07-05 21:23:04 +00002503 Operands.push_back(AArch64Operand::CreateBarrier(
2504 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002505 Parser.Lex(); // Consume the option
2506
2507 return MatchOperand_Success;
2508}
2509
Alex Bradbury58eba092016-11-01 16:32:05 +00002510OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002511AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002512 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002513 const AsmToken &Tok = Parser.getTok();
2514
2515 if (Tok.isNot(AsmToken::Identifier))
2516 return MatchOperand_NoMatch;
2517
Tim Northovere6ae6762016-07-05 21:23:04 +00002518 int MRSReg, MSRReg;
2519 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2520 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2521 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2522 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2523 } else
2524 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002525
Tim Northovere6ae6762016-07-05 21:23:04 +00002526 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2527 unsigned PStateImm = -1;
2528 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2529 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002530
Tim Northovere6ae6762016-07-05 21:23:04 +00002531 Operands.push_back(
2532 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2533 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002534 Parser.Lex(); // Eat identifier
2535
2536 return MatchOperand_Success;
2537}
2538
2539/// tryParseVectorRegister - Parse a vector register operand.
2540bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002541 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002542 if (Parser.getTok().isNot(AsmToken::Identifier))
2543 return true;
2544
2545 SMLoc S = getLoc();
2546 // Check for a vector register specifier first.
2547 StringRef Kind;
2548 int64_t Reg = tryMatchVectorRegister(Kind, false);
2549 if (Reg == -1)
2550 return true;
2551 Operands.push_back(
2552 AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2553 // If there was an explicit qualifier, that goes on as a literal text
2554 // operand.
2555 if (!Kind.empty())
2556 Operands.push_back(
2557 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2558
2559 // If there is an index specifier following the register, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002560 SMLoc SIdx = getLoc();
2561 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002562 const MCExpr *ImmVal;
2563 if (getParser().parseExpression(ImmVal))
2564 return false;
2565 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2566 if (!MCE) {
2567 TokError("immediate value expected for vector index");
2568 return false;
2569 }
2570
2571 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002572
Nirav Davee833c6c2016-11-08 18:31:04 +00002573 if (parseToken(AsmToken::RBrac, "']' expected"))
2574 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002575
2576 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2577 E, getContext()));
2578 }
2579
2580 return false;
2581}
2582
2583/// parseRegister - Parse a non-vector register operand.
2584bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2585 SMLoc S = getLoc();
2586 // Try for a vector register.
2587 if (!tryParseVectorRegister(Operands))
2588 return false;
2589
2590 // Try for a scalar register.
2591 int64_t Reg = tryParseRegister();
2592 if (Reg == -1)
2593 return true;
2594 Operands.push_back(
2595 AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2596
Tim Northover3b0846e2014-05-24 12:50:23 +00002597 return false;
2598}
2599
2600bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002601 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002602 bool HasELFModifier = false;
2603 AArch64MCExpr::VariantKind RefKind;
2604
Nirav Davee833c6c2016-11-08 18:31:04 +00002605 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002606 HasELFModifier = true;
2607
Nirav Davee833c6c2016-11-08 18:31:04 +00002608 if (Parser.getTok().isNot(AsmToken::Identifier))
2609 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002610
2611 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2612 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2613 .Case("lo12", AArch64MCExpr::VK_LO12)
2614 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2615 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2616 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2617 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2618 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2619 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2620 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2621 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2622 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2623 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2624 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2625 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2626 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2627 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2628 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2629 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2630 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2631 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2632 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2633 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2634 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2635 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2636 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2637 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2638 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2639 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2640 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2641 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2642 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2643 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2644 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2645 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2646 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2647 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
2648 .Default(AArch64MCExpr::VK_INVALID);
2649
Nirav Davee833c6c2016-11-08 18:31:04 +00002650 if (RefKind == AArch64MCExpr::VK_INVALID)
2651 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002652
2653 Parser.Lex(); // Eat identifier
2654
Nirav Davee833c6c2016-11-08 18:31:04 +00002655 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002656 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002657 }
2658
2659 if (getParser().parseExpression(ImmVal))
2660 return true;
2661
2662 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002663 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002664
2665 return false;
2666}
2667
2668/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
2669bool AArch64AsmParser::parseVectorList(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002670 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002671 assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
2672 SMLoc S = getLoc();
2673 Parser.Lex(); // Eat left bracket token.
2674 StringRef Kind;
2675 int64_t FirstReg = tryMatchVectorRegister(Kind, true);
2676 if (FirstReg == -1)
2677 return true;
2678 int64_t PrevReg = FirstReg;
2679 unsigned Count = 1;
2680
Nirav Davee833c6c2016-11-08 18:31:04 +00002681 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002682 SMLoc Loc = getLoc();
2683 StringRef NextKind;
2684 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2685 if (Reg == -1)
2686 return true;
2687 // Any Kind suffices must match on all regs in the list.
2688 if (Kind != NextKind)
2689 return Error(Loc, "mismatched register size suffix");
2690
2691 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2692
2693 if (Space == 0 || Space > 3) {
2694 return Error(Loc, "invalid number of vectors");
2695 }
2696
2697 Count += Space;
2698 }
2699 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002700 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002701 SMLoc Loc = getLoc();
2702 StringRef NextKind;
2703 int64_t Reg = tryMatchVectorRegister(NextKind, true);
2704 if (Reg == -1)
2705 return true;
2706 // Any Kind suffices must match on all regs in the list.
2707 if (Kind != NextKind)
2708 return Error(Loc, "mismatched register size suffix");
2709
2710 // Registers must be incremental (with wraparound at 31)
2711 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
2712 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
2713 return Error(Loc, "registers must be sequential");
2714
2715 PrevReg = Reg;
2716 ++Count;
2717 }
2718 }
2719
Nirav Davee833c6c2016-11-08 18:31:04 +00002720 if (parseToken(AsmToken::RCurly, "'}' expected"))
2721 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002722
2723 if (Count > 4)
2724 return Error(S, "invalid number of vectors");
2725
2726 unsigned NumElements = 0;
2727 char ElementKind = 0;
2728 if (!Kind.empty())
2729 parseValidVectorKind(Kind, NumElements, ElementKind);
2730
2731 Operands.push_back(AArch64Operand::CreateVectorList(
2732 FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
2733
2734 // If there is an index specifier following the list, parse that too.
Nirav Davee833c6c2016-11-08 18:31:04 +00002735 SMLoc SIdx = getLoc();
2736 if (parseOptionalToken(AsmToken::LBrac)) { // Eat left bracket token.
Tim Northover3b0846e2014-05-24 12:50:23 +00002737 const MCExpr *ImmVal;
2738 if (getParser().parseExpression(ImmVal))
2739 return false;
2740 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2741 if (!MCE) {
2742 TokError("immediate value expected for vector index");
2743 return false;
2744 }
2745
2746 SMLoc E = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002747 if (parseToken(AsmToken::RBrac, "']' expected"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002748 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00002749
2750 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2751 E, getContext()));
2752 }
2753 return false;
2754}
2755
Alex Bradbury58eba092016-11-01 16:32:05 +00002756OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002757AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002758 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002759 const AsmToken &Tok = Parser.getTok();
2760 if (!Tok.is(AsmToken::Identifier))
2761 return MatchOperand_NoMatch;
2762
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002763 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
Tim Northover3b0846e2014-05-24 12:50:23 +00002764
2765 MCContext &Ctx = getContext();
2766 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2767 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
2768 return MatchOperand_NoMatch;
2769
2770 SMLoc S = getLoc();
2771 Parser.Lex(); // Eat register
2772
Nirav Davee833c6c2016-11-08 18:31:04 +00002773 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002774 Operands.push_back(
2775 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2776 return MatchOperand_Success;
2777 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002778
Nirav Davee833c6c2016-11-08 18:31:04 +00002779 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002780
2781 if (Parser.getTok().isNot(AsmToken::Integer)) {
2782 Error(getLoc(), "index must be absent or #0");
2783 return MatchOperand_ParseFail;
2784 }
2785
2786 const MCExpr *ImmVal;
2787 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
2788 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
2789 Error(getLoc(), "index must be absent or #0");
2790 return MatchOperand_ParseFail;
2791 }
2792
2793 Operands.push_back(
2794 AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
2795 return MatchOperand_Success;
2796}
2797
2798/// parseOperand - Parse a arm instruction operand. For now this parses the
2799/// operand regardless of the mnemonic.
2800bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
2801 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002802 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002803 // Check if the current operand has a custom associated parser, if so, try to
2804 // custom parse the operand, or fallback to the general approach.
2805 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2806 if (ResTy == MatchOperand_Success)
2807 return false;
2808 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2809 // there was a match, but an error occurred, in which case, just return that
2810 // the operand parsing failed.
2811 if (ResTy == MatchOperand_ParseFail)
2812 return true;
2813
2814 // Nothing custom, so do general case parsing.
2815 SMLoc S, E;
2816 switch (getLexer().getKind()) {
2817 default: {
2818 SMLoc S = getLoc();
2819 const MCExpr *Expr;
2820 if (parseSymbolicImmVal(Expr))
2821 return Error(S, "invalid operand");
2822
2823 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2824 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2825 return false;
2826 }
2827 case AsmToken::LBrac: {
2828 SMLoc Loc = Parser.getTok().getLoc();
2829 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
2830 getContext()));
2831 Parser.Lex(); // Eat '['
2832
2833 // There's no comma after a '[', so we can parse the next operand
2834 // immediately.
2835 return parseOperand(Operands, false, false);
2836 }
2837 case AsmToken::LCurly:
2838 return parseVectorList(Operands);
2839 case AsmToken::Identifier: {
2840 // If we're expecting a Condition Code operand, then just parse that.
2841 if (isCondCode)
2842 return parseCondCode(Operands, invertCondCode);
2843
2844 // If it's a register name, parse it.
2845 if (!parseRegister(Operands))
2846 return false;
2847
2848 // This could be an optional "shift" or "extend" operand.
2849 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
2850 // We can only continue if no tokens were eaten.
2851 if (GotShift != MatchOperand_NoMatch)
2852 return GotShift;
2853
2854 // This was not a register so parse other operands that start with an
2855 // identifier (like labels) as expressions and create them as immediates.
2856 const MCExpr *IdVal;
2857 S = getLoc();
2858 if (getParser().parseExpression(IdVal))
2859 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002860 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2861 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
2862 return false;
2863 }
2864 case AsmToken::Integer:
2865 case AsmToken::Real:
2866 case AsmToken::Hash: {
2867 // #42 -> immediate.
2868 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00002869
2870 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002871
2872 // Parse a negative sign
2873 bool isNegative = false;
2874 if (Parser.getTok().is(AsmToken::Minus)) {
2875 isNegative = true;
2876 // We need to consume this token only when we have a Real, otherwise
2877 // we let parseSymbolicImmVal take care of it
2878 if (Parser.getLexer().peekTok().is(AsmToken::Real))
2879 Parser.Lex();
2880 }
2881
2882 // The only Real that should come through here is a literal #0.0 for
2883 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
2884 // so convert the value.
2885 const AsmToken &Tok = Parser.getTok();
2886 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002887 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002888 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2889 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
2890 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
2891 Mnemonic != "fcmlt")
2892 return TokError("unexpected floating point literal");
2893 else if (IntVal != 0 || isNegative)
2894 return TokError("expected floating-point constant #0.0");
2895 Parser.Lex(); // Eat the token.
2896
2897 Operands.push_back(
2898 AArch64Operand::CreateToken("#0", false, S, getContext()));
2899 Operands.push_back(
2900 AArch64Operand::CreateToken(".0", false, S, getContext()));
2901 return false;
2902 }
2903
2904 const MCExpr *ImmVal;
2905 if (parseSymbolicImmVal(ImmVal))
2906 return true;
2907
2908 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2909 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
2910 return false;
2911 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002912 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00002913 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002914 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00002915 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002916 Parser.Lex(); // Eat '='
2917 const MCExpr *SubExprVal;
2918 if (getParser().parseExpression(SubExprVal))
2919 return true;
2920
David Peixottoae5ba762014-07-18 16:05:14 +00002921 if (Operands.size() < 2 ||
2922 !static_cast<AArch64Operand &>(*Operands[1]).isReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00002923 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00002924
2925 bool IsXReg =
2926 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
2927 Operands[1]->getReg());
2928
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002929 MCContext& Ctx = getContext();
2930 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
2931 // 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 +00002932 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002933 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
2934 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
2935 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
2936 ShiftAmt += 16;
2937 Imm >>= 16;
2938 }
2939 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
2940 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
2941 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00002942 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002943 if (ShiftAmt)
2944 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
2945 ShiftAmt, true, S, E, Ctx));
2946 return false;
2947 }
David Peixottoae5ba762014-07-18 16:05:14 +00002948 APInt Simm = APInt(64, Imm << ShiftAmt);
2949 // check if the immediate is an unsigned or signed 32-bit int for W regs
2950 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
2951 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002952 }
2953 // 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 +00002954 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00002955 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00002956 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
2957 return false;
2958 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002959 }
2960}
2961
2962/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
2963/// operands.
2964bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
2965 StringRef Name, SMLoc NameLoc,
2966 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002967 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002968 Name = StringSwitch<StringRef>(Name.lower())
2969 .Case("beq", "b.eq")
2970 .Case("bne", "b.ne")
2971 .Case("bhs", "b.hs")
2972 .Case("bcs", "b.cs")
2973 .Case("blo", "b.lo")
2974 .Case("bcc", "b.cc")
2975 .Case("bmi", "b.mi")
2976 .Case("bpl", "b.pl")
2977 .Case("bvs", "b.vs")
2978 .Case("bvc", "b.vc")
2979 .Case("bhi", "b.hi")
2980 .Case("bls", "b.ls")
2981 .Case("bge", "b.ge")
2982 .Case("blt", "b.lt")
2983 .Case("bgt", "b.gt")
2984 .Case("ble", "b.le")
2985 .Case("bal", "b.al")
2986 .Case("bnv", "b.nv")
2987 .Default(Name);
2988
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002989 // First check for the AArch64-specific .req directive.
2990 if (Parser.getTok().is(AsmToken::Identifier) &&
2991 Parser.getTok().getIdentifier() == ".req") {
2992 parseDirectiveReq(Name, NameLoc);
2993 // We always return 'error' for this, as we're done with this
2994 // statement and don't need to match the 'instruction."
2995 return true;
2996 }
2997
Tim Northover3b0846e2014-05-24 12:50:23 +00002998 // Create the leading tokens for the mnemonic, split by '.' characters.
2999 size_t Start = 0, Next = Name.find('.');
3000 StringRef Head = Name.slice(Start, Next);
3001
3002 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003003 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3004 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003005
3006 Operands.push_back(
3007 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3008 Mnemonic = Head;
3009
3010 // Handle condition codes for a branch mnemonic
3011 if (Head == "b" && Next != StringRef::npos) {
3012 Start = Next;
3013 Next = Name.find('.', Start + 1);
3014 Head = Name.slice(Start + 1, Next);
3015
3016 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3017 (Head.data() - Name.data()));
3018 AArch64CC::CondCode CC = parseCondCodeString(Head);
3019 if (CC == AArch64CC::Invalid)
3020 return Error(SuffixLoc, "invalid condition code");
3021 Operands.push_back(
3022 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3023 Operands.push_back(
3024 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3025 }
3026
3027 // Add the remaining tokens in the mnemonic.
3028 while (Next != StringRef::npos) {
3029 Start = Next;
3030 Next = Name.find('.', Start + 1);
3031 Head = Name.slice(Start, Next);
3032 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3033 (Head.data() - Name.data()) + 1);
3034 Operands.push_back(
3035 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3036 }
3037
3038 // Conditional compare instructions have a Condition Code operand, which needs
3039 // to be parsed and an immediate operand created.
3040 bool condCodeFourthOperand =
3041 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3042 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3043 Head == "csinc" || Head == "csinv" || Head == "csneg");
3044
3045 // These instructions are aliases to some of the conditional select
3046 // instructions. However, the condition code is inverted in the aliased
3047 // instruction.
3048 //
3049 // FIXME: Is this the correct way to handle these? Or should the parser
3050 // generate the aliased instructions directly?
3051 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3052 bool condCodeThirdOperand =
3053 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3054
3055 // Read the remaining operands.
3056 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3057 // Read the first operand.
3058 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003059 return true;
3060 }
3061
3062 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003063 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003064 // Parse and remember the operand.
3065 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3066 (N == 3 && condCodeThirdOperand) ||
3067 (N == 2 && condCodeSecondOperand),
3068 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003069 return true;
3070 }
3071
3072 // After successfully parsing some operands there are two special cases to
3073 // consider (i.e. notional operands not separated by commas). Both are due
3074 // to memory specifiers:
3075 // + An RBrac will end an address for load/store/prefetch
3076 // + An '!' will indicate a pre-indexed operation.
3077 //
3078 // It's someone else's responsibility to make sure these tokens are sane
3079 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003080
Nirav Davee833c6c2016-11-08 18:31:04 +00003081 SMLoc RLoc = Parser.getTok().getLoc();
3082 if (parseOptionalToken(AsmToken::RBrac))
3083 Operands.push_back(
3084 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3085 SMLoc ELoc = Parser.getTok().getLoc();
3086 if (parseOptionalToken(AsmToken::Exclaim))
3087 Operands.push_back(
3088 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003089
3090 ++N;
3091 }
3092 }
3093
Nirav Davee833c6c2016-11-08 18:31:04 +00003094 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3095 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003096
Tim Northover3b0846e2014-05-24 12:50:23 +00003097 return false;
3098}
3099
3100// FIXME: This entire function is a giant hack to provide us with decent
3101// operand range validation/diagnostics until TableGen/MC can be extended
3102// to support autogeneration of this kind of validation.
3103bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3104 SmallVectorImpl<SMLoc> &Loc) {
3105 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3106 // Check for indexed addressing modes w/ the base register being the
3107 // same as a destination/source register or pair load where
3108 // the Rt == Rt2. All of those are undefined behaviour.
3109 switch (Inst.getOpcode()) {
3110 case AArch64::LDPSWpre:
3111 case AArch64::LDPWpost:
3112 case AArch64::LDPWpre:
3113 case AArch64::LDPXpost:
3114 case AArch64::LDPXpre: {
3115 unsigned Rt = Inst.getOperand(1).getReg();
3116 unsigned Rt2 = Inst.getOperand(2).getReg();
3117 unsigned Rn = Inst.getOperand(3).getReg();
3118 if (RI->isSubRegisterEq(Rn, Rt))
3119 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3120 "is also a destination");
3121 if (RI->isSubRegisterEq(Rn, Rt2))
3122 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3123 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003124 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003125 }
3126 case AArch64::LDPDi:
3127 case AArch64::LDPQi:
3128 case AArch64::LDPSi:
3129 case AArch64::LDPSWi:
3130 case AArch64::LDPWi:
3131 case AArch64::LDPXi: {
3132 unsigned Rt = Inst.getOperand(0).getReg();
3133 unsigned Rt2 = Inst.getOperand(1).getReg();
3134 if (Rt == Rt2)
3135 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3136 break;
3137 }
3138 case AArch64::LDPDpost:
3139 case AArch64::LDPDpre:
3140 case AArch64::LDPQpost:
3141 case AArch64::LDPQpre:
3142 case AArch64::LDPSpost:
3143 case AArch64::LDPSpre:
3144 case AArch64::LDPSWpost: {
3145 unsigned Rt = Inst.getOperand(1).getReg();
3146 unsigned Rt2 = Inst.getOperand(2).getReg();
3147 if (Rt == Rt2)
3148 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3149 break;
3150 }
3151 case AArch64::STPDpost:
3152 case AArch64::STPDpre:
3153 case AArch64::STPQpost:
3154 case AArch64::STPQpre:
3155 case AArch64::STPSpost:
3156 case AArch64::STPSpre:
3157 case AArch64::STPWpost:
3158 case AArch64::STPWpre:
3159 case AArch64::STPXpost:
3160 case AArch64::STPXpre: {
3161 unsigned Rt = Inst.getOperand(1).getReg();
3162 unsigned Rt2 = Inst.getOperand(2).getReg();
3163 unsigned Rn = Inst.getOperand(3).getReg();
3164 if (RI->isSubRegisterEq(Rn, Rt))
3165 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3166 "is also a source");
3167 if (RI->isSubRegisterEq(Rn, Rt2))
3168 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3169 "is also a source");
3170 break;
3171 }
3172 case AArch64::LDRBBpre:
3173 case AArch64::LDRBpre:
3174 case AArch64::LDRHHpre:
3175 case AArch64::LDRHpre:
3176 case AArch64::LDRSBWpre:
3177 case AArch64::LDRSBXpre:
3178 case AArch64::LDRSHWpre:
3179 case AArch64::LDRSHXpre:
3180 case AArch64::LDRSWpre:
3181 case AArch64::LDRWpre:
3182 case AArch64::LDRXpre:
3183 case AArch64::LDRBBpost:
3184 case AArch64::LDRBpost:
3185 case AArch64::LDRHHpost:
3186 case AArch64::LDRHpost:
3187 case AArch64::LDRSBWpost:
3188 case AArch64::LDRSBXpost:
3189 case AArch64::LDRSHWpost:
3190 case AArch64::LDRSHXpost:
3191 case AArch64::LDRSWpost:
3192 case AArch64::LDRWpost:
3193 case AArch64::LDRXpost: {
3194 unsigned Rt = Inst.getOperand(1).getReg();
3195 unsigned Rn = Inst.getOperand(2).getReg();
3196 if (RI->isSubRegisterEq(Rn, Rt))
3197 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3198 "is also a source");
3199 break;
3200 }
3201 case AArch64::STRBBpost:
3202 case AArch64::STRBpost:
3203 case AArch64::STRHHpost:
3204 case AArch64::STRHpost:
3205 case AArch64::STRWpost:
3206 case AArch64::STRXpost:
3207 case AArch64::STRBBpre:
3208 case AArch64::STRBpre:
3209 case AArch64::STRHHpre:
3210 case AArch64::STRHpre:
3211 case AArch64::STRWpre:
3212 case AArch64::STRXpre: {
3213 unsigned Rt = Inst.getOperand(1).getReg();
3214 unsigned Rn = Inst.getOperand(2).getReg();
3215 if (RI->isSubRegisterEq(Rn, Rt))
3216 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3217 "is also a source");
3218 break;
3219 }
3220 }
3221
3222 // Now check immediate ranges. Separate from the above as there is overlap
3223 // in the instructions being checked and this keeps the nested conditionals
3224 // to a minimum.
3225 switch (Inst.getOpcode()) {
3226 case AArch64::ADDSWri:
3227 case AArch64::ADDSXri:
3228 case AArch64::ADDWri:
3229 case AArch64::ADDXri:
3230 case AArch64::SUBSWri:
3231 case AArch64::SUBSXri:
3232 case AArch64::SUBWri:
3233 case AArch64::SUBXri: {
3234 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3235 // some slight duplication here.
3236 if (Inst.getOperand(2).isExpr()) {
3237 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3238 AArch64MCExpr::VariantKind ELFRefKind;
3239 MCSymbolRefExpr::VariantKind DarwinRefKind;
3240 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003241 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3242
3243 // Only allow these with ADDXri.
3244 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3245 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3246 Inst.getOpcode() == AArch64::ADDXri)
3247 return false;
3248
3249 // Only allow these with ADDXri/ADDWri
3250 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3251 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3252 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3253 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3254 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3255 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3256 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3257 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3258 (Inst.getOpcode() == AArch64::ADDXri ||
3259 Inst.getOpcode() == AArch64::ADDWri))
3260 return false;
3261
3262 // Don't allow symbol refs in the immediate field otherwise
3263 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3264 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3265 // 'cmp w0, 'borked')
3266 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003267 }
Diana Picusc93518d2016-10-11 09:17:47 +00003268 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003269 }
3270 return false;
3271 }
3272 default:
3273 return false;
3274 }
3275}
3276
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003277std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS);
3278
3279bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3280 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003281 switch (ErrCode) {
3282 case Match_MissingFeature:
3283 return Error(Loc,
3284 "instruction requires a CPU feature not currently enabled");
3285 case Match_InvalidOperand:
3286 return Error(Loc, "invalid operand for instruction");
3287 case Match_InvalidSuffix:
3288 return Error(Loc, "invalid type suffix for instruction");
3289 case Match_InvalidCondCode:
3290 return Error(Loc, "expected AArch64 condition code");
3291 case Match_AddSubRegExtendSmall:
3292 return Error(Loc,
3293 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3294 case Match_AddSubRegExtendLarge:
3295 return Error(Loc,
3296 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3297 case Match_AddSubSecondSource:
3298 return Error(Loc,
3299 "expected compatible register, symbol or integer in range [0, 4095]");
3300 case Match_LogicalSecondSource:
3301 return Error(Loc, "expected compatible register or logical immediate");
3302 case Match_InvalidMovImm32Shift:
3303 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3304 case Match_InvalidMovImm64Shift:
3305 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3306 case Match_AddSubRegShift32:
3307 return Error(Loc,
3308 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3309 case Match_AddSubRegShift64:
3310 return Error(Loc,
3311 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3312 case Match_InvalidFPImm:
3313 return Error(Loc,
3314 "expected compatible register or floating-point constant");
3315 case Match_InvalidMemoryIndexedSImm9:
3316 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003317 case Match_InvalidMemoryIndexedSImm10:
3318 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003319 case Match_InvalidMemoryIndexed4SImm7:
3320 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3321 case Match_InvalidMemoryIndexed8SImm7:
3322 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3323 case Match_InvalidMemoryIndexed16SImm7:
3324 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3325 case Match_InvalidMemoryWExtend8:
3326 return Error(Loc,
3327 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3328 case Match_InvalidMemoryWExtend16:
3329 return Error(Loc,
3330 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3331 case Match_InvalidMemoryWExtend32:
3332 return Error(Loc,
3333 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3334 case Match_InvalidMemoryWExtend64:
3335 return Error(Loc,
3336 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3337 case Match_InvalidMemoryWExtend128:
3338 return Error(Loc,
3339 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3340 case Match_InvalidMemoryXExtend8:
3341 return Error(Loc,
3342 "expected 'lsl' or 'sxtx' with optional shift of #0");
3343 case Match_InvalidMemoryXExtend16:
3344 return Error(Loc,
3345 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3346 case Match_InvalidMemoryXExtend32:
3347 return Error(Loc,
3348 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3349 case Match_InvalidMemoryXExtend64:
3350 return Error(Loc,
3351 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3352 case Match_InvalidMemoryXExtend128:
3353 return Error(Loc,
3354 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3355 case Match_InvalidMemoryIndexed1:
3356 return Error(Loc, "index must be an integer in range [0, 4095].");
3357 case Match_InvalidMemoryIndexed2:
3358 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3359 case Match_InvalidMemoryIndexed4:
3360 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3361 case Match_InvalidMemoryIndexed8:
3362 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3363 case Match_InvalidMemoryIndexed16:
3364 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003365 case Match_InvalidImm0_1:
3366 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003367 case Match_InvalidImm0_7:
3368 return Error(Loc, "immediate must be an integer in range [0, 7].");
3369 case Match_InvalidImm0_15:
3370 return Error(Loc, "immediate must be an integer in range [0, 15].");
3371 case Match_InvalidImm0_31:
3372 return Error(Loc, "immediate must be an integer in range [0, 31].");
3373 case Match_InvalidImm0_63:
3374 return Error(Loc, "immediate must be an integer in range [0, 63].");
3375 case Match_InvalidImm0_127:
3376 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003377 case Match_InvalidImm0_255:
3378 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003379 case Match_InvalidImm0_65535:
3380 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3381 case Match_InvalidImm1_8:
3382 return Error(Loc, "immediate must be an integer in range [1, 8].");
3383 case Match_InvalidImm1_16:
3384 return Error(Loc, "immediate must be an integer in range [1, 16].");
3385 case Match_InvalidImm1_32:
3386 return Error(Loc, "immediate must be an integer in range [1, 32].");
3387 case Match_InvalidImm1_64:
3388 return Error(Loc, "immediate must be an integer in range [1, 64].");
3389 case Match_InvalidIndex1:
3390 return Error(Loc, "expected lane specifier '[1]'");
3391 case Match_InvalidIndexB:
3392 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3393 case Match_InvalidIndexH:
3394 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3395 case Match_InvalidIndexS:
3396 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3397 case Match_InvalidIndexD:
3398 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3399 case Match_InvalidLabel:
3400 return Error(Loc, "expected label or encodable integer pc offset");
3401 case Match_MRS:
3402 return Error(Loc, "expected readable system register");
3403 case Match_MSR:
3404 return Error(Loc, "expected writable system register or pstate");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003405 case Match_MnemonicFail: {
3406 std::string Suggestion = AArch64MnemonicSpellCheck(
3407 ((AArch64Operand &)*Operands[0]).getToken(),
3408 ComputeAvailableFeatures(STI->getFeatureBits()));
3409 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3410 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003411 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003412 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003413 }
3414}
3415
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003416static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003417
3418bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3419 OperandVector &Operands,
3420 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003421 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003422 bool MatchingInlineAsm) {
3423 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003424 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3425 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003426
David Blaikie960ea3f2014-06-08 16:18:35 +00003427 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003428 unsigned NumOperands = Operands.size();
3429
3430 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003431 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3432 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3433 if (Op2.isReg() && Op3.isImm()) {
3434 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003435 if (Op3CE) {
3436 uint64_t Op3Val = Op3CE->getValue();
3437 uint64_t NewOp3Val = 0;
3438 uint64_t NewOp4Val = 0;
3439 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003440 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003441 NewOp3Val = (32 - Op3Val) & 0x1f;
3442 NewOp4Val = 31 - Op3Val;
3443 } else {
3444 NewOp3Val = (64 - Op3Val) & 0x3f;
3445 NewOp4Val = 63 - Op3Val;
3446 }
3447
Jim Grosbach13760bd2015-05-30 01:25:56 +00003448 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3449 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003450
3451 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003452 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003453 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003454 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3455 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3456 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003457 }
3458 }
Tim Northover03b99f62015-04-30 18:28:58 +00003459 } else if (NumOperands == 4 && Tok == "bfc") {
3460 // FIXME: Horrible hack to handle BFC->BFM alias.
3461 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3462 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3463 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3464
3465 if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3466 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3467 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3468
3469 if (LSBCE && WidthCE) {
3470 uint64_t LSB = LSBCE->getValue();
3471 uint64_t Width = WidthCE->getValue();
3472
3473 uint64_t RegWidth = 0;
3474 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3475 Op1.getReg()))
3476 RegWidth = 64;
3477 else
3478 RegWidth = 32;
3479
3480 if (LSB >= RegWidth)
3481 return Error(LSBOp.getStartLoc(),
3482 "expected integer in range [0, 31]");
3483 if (Width < 1 || Width > RegWidth)
3484 return Error(WidthOp.getStartLoc(),
3485 "expected integer in range [1, 32]");
3486
3487 uint64_t ImmR = 0;
3488 if (RegWidth == 32)
3489 ImmR = (32 - LSB) & 0x1f;
3490 else
3491 ImmR = (64 - LSB) & 0x3f;
3492
3493 uint64_t ImmS = Width - 1;
3494
3495 if (ImmR != 0 && ImmS >= ImmR)
3496 return Error(WidthOp.getStartLoc(),
3497 "requested insert overflows register");
3498
Jim Grosbach13760bd2015-05-30 01:25:56 +00003499 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3500 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003501 Operands[0] = AArch64Operand::CreateToken(
3502 "bfm", false, Op.getStartLoc(), getContext());
3503 Operands[2] = AArch64Operand::CreateReg(
3504 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3505 SMLoc(), getContext());
3506 Operands[3] = AArch64Operand::CreateImm(
3507 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3508 Operands.emplace_back(
3509 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3510 WidthOp.getEndLoc(), getContext()));
3511 }
3512 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003513 } else if (NumOperands == 5) {
3514 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3515 // UBFIZ -> UBFM aliases.
3516 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003517 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3518 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3519 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003520
David Blaikie960ea3f2014-06-08 16:18:35 +00003521 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3522 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3523 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003524
3525 if (Op3CE && Op4CE) {
3526 uint64_t Op3Val = Op3CE->getValue();
3527 uint64_t Op4Val = Op4CE->getValue();
3528
3529 uint64_t RegWidth = 0;
3530 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003531 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003532 RegWidth = 64;
3533 else
3534 RegWidth = 32;
3535
3536 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003537 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003538 "expected integer in range [0, 31]");
3539 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003540 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003541 "expected integer in range [1, 32]");
3542
3543 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003544 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003545 NewOp3Val = (32 - Op3Val) & 0x1f;
3546 else
3547 NewOp3Val = (64 - Op3Val) & 0x3f;
3548
3549 uint64_t NewOp4Val = Op4Val - 1;
3550
3551 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003552 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003553 "requested insert overflows register");
3554
3555 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003556 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003557 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003558 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003559 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003560 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003561 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003562 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003563 if (Tok == "bfi")
3564 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003565 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003566 else if (Tok == "sbfiz")
3567 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003568 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003569 else if (Tok == "ubfiz")
3570 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003571 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003572 else
3573 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003574 }
3575 }
3576
3577 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3578 // UBFX -> UBFM aliases.
3579 } else if (NumOperands == 5 &&
3580 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003581 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3582 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3583 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003584
David Blaikie960ea3f2014-06-08 16:18:35 +00003585 if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
3586 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3587 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003588
3589 if (Op3CE && Op4CE) {
3590 uint64_t Op3Val = Op3CE->getValue();
3591 uint64_t Op4Val = Op4CE->getValue();
3592
3593 uint64_t RegWidth = 0;
3594 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003595 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003596 RegWidth = 64;
3597 else
3598 RegWidth = 32;
3599
3600 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003601 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003602 "expected integer in range [0, 31]");
3603 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003604 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003605 "expected integer in range [1, 32]");
3606
3607 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3608
3609 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003610 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003611 "requested extract overflows register");
3612
3613 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003614 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003615 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003616 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003617 if (Tok == "bfxil")
3618 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003619 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003620 else if (Tok == "sbfx")
3621 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003622 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003623 else if (Tok == "ubfx")
3624 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003625 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003626 else
3627 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003628 }
3629 }
3630 }
3631 }
3632 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
3633 // InstAlias can't quite handle this since the reg classes aren't
3634 // subclasses.
3635 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
3636 // The source register can be Wn here, but the matcher expects a
3637 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003638 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3639 if (Op.isReg()) {
3640 unsigned Reg = getXRegFromWReg(Op.getReg());
3641 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3642 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003643 }
3644 }
3645 // FIXME: Likewise for sxt[bh] with a Xd dst operand
3646 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003647 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3648 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003649 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003650 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003651 // The source register can be Wn here, but the matcher expects a
3652 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003653 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
3654 if (Op.isReg()) {
3655 unsigned Reg = getXRegFromWReg(Op.getReg());
3656 Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3657 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003658 }
3659 }
3660 }
3661 // FIXME: Likewise for uxt[bh] with a Xd dst operand
3662 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003663 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3664 if (Op.isReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00003665 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003666 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003667 // The source register can be Wn here, but the matcher expects a
3668 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00003669 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
3670 if (Op.isReg()) {
3671 unsigned Reg = getWRegFromXReg(Op.getReg());
3672 Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
3673 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003674 }
3675 }
3676 }
3677
Tim Northover3b0846e2014-05-24 12:50:23 +00003678 MCInst Inst;
3679 // First try to match against the secondary set of tables containing the
3680 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
3681 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003682 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00003683
3684 // If that fails, try against the alternate table containing long-form NEON:
3685 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003686 if (MatchResult != Match_Success) {
3687 // But first, save the short-form match result: we can use it in case the
3688 // long-form match also fails.
3689 auto ShortFormNEONErrorInfo = ErrorInfo;
3690 auto ShortFormNEONMatchResult = MatchResult;
3691
Tim Northover3b0846e2014-05-24 12:50:23 +00003692 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003693 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00003694
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003695 // Now, both matches failed, and the long-form match failed on the mnemonic
3696 // suffix token operand. The short-form match failure is probably more
3697 // relevant: use it instead.
3698 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00003699 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00003700 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
3701 MatchResult = ShortFormNEONMatchResult;
3702 ErrorInfo = ShortFormNEONErrorInfo;
3703 }
3704 }
3705
Tim Northover3b0846e2014-05-24 12:50:23 +00003706 switch (MatchResult) {
3707 case Match_Success: {
3708 // Perform range checking and other semantic validations
3709 SmallVector<SMLoc, 8> OperandLocs;
3710 NumOperands = Operands.size();
3711 for (unsigned i = 1; i < NumOperands; ++i)
3712 OperandLocs.push_back(Operands[i]->getStartLoc());
3713 if (validateInstruction(Inst, OperandLocs))
3714 return true;
3715
3716 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003717 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00003718 return false;
3719 }
3720 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003721 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003722 // Special case the error message for the very common case where only
3723 // a single subtarget feature is missing (neon, e.g.).
3724 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003725 uint64_t Mask = 1;
3726 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
3727 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003728 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003729 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00003730 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003731 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00003732 }
3733 return Error(IDLoc, Msg);
3734 }
3735 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003736 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003737 case Match_InvalidOperand: {
3738 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00003739
Tim Northover26bb14e2014-08-18 11:49:42 +00003740 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003741 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003742 return Error(IDLoc, "too few operands for instruction",
3743 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003744
David Blaikie960ea3f2014-06-08 16:18:35 +00003745 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003746 if (ErrorLoc == SMLoc())
3747 ErrorLoc = IDLoc;
3748 }
3749 // If the match failed on a suffix token operand, tweak the diagnostic
3750 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00003751 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
3752 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00003753 MatchResult = Match_InvalidSuffix;
3754
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003755 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003756 }
3757 case Match_InvalidMemoryIndexed1:
3758 case Match_InvalidMemoryIndexed2:
3759 case Match_InvalidMemoryIndexed4:
3760 case Match_InvalidMemoryIndexed8:
3761 case Match_InvalidMemoryIndexed16:
3762 case Match_InvalidCondCode:
3763 case Match_AddSubRegExtendSmall:
3764 case Match_AddSubRegExtendLarge:
3765 case Match_AddSubSecondSource:
3766 case Match_LogicalSecondSource:
3767 case Match_AddSubRegShift32:
3768 case Match_AddSubRegShift64:
3769 case Match_InvalidMovImm32Shift:
3770 case Match_InvalidMovImm64Shift:
3771 case Match_InvalidFPImm:
3772 case Match_InvalidMemoryWExtend8:
3773 case Match_InvalidMemoryWExtend16:
3774 case Match_InvalidMemoryWExtend32:
3775 case Match_InvalidMemoryWExtend64:
3776 case Match_InvalidMemoryWExtend128:
3777 case Match_InvalidMemoryXExtend8:
3778 case Match_InvalidMemoryXExtend16:
3779 case Match_InvalidMemoryXExtend32:
3780 case Match_InvalidMemoryXExtend64:
3781 case Match_InvalidMemoryXExtend128:
3782 case Match_InvalidMemoryIndexed4SImm7:
3783 case Match_InvalidMemoryIndexed8SImm7:
3784 case Match_InvalidMemoryIndexed16SImm7:
3785 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00003786 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003787 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00003788 case Match_InvalidImm0_7:
3789 case Match_InvalidImm0_15:
3790 case Match_InvalidImm0_31:
3791 case Match_InvalidImm0_63:
3792 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003793 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00003794 case Match_InvalidImm0_65535:
3795 case Match_InvalidImm1_8:
3796 case Match_InvalidImm1_16:
3797 case Match_InvalidImm1_32:
3798 case Match_InvalidImm1_64:
3799 case Match_InvalidIndex1:
3800 case Match_InvalidIndexB:
3801 case Match_InvalidIndexH:
3802 case Match_InvalidIndexS:
3803 case Match_InvalidIndexD:
3804 case Match_InvalidLabel:
3805 case Match_MSR:
3806 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00003807 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00003808 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003809 // Any time we get here, there's nothing fancy to do. Just get the
3810 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00003811 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003812 if (ErrorLoc == SMLoc())
3813 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003814 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003815 }
3816 }
3817
3818 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003819}
3820
3821/// ParseDirective parses the arm specific directives
3822bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00003823 const MCObjectFileInfo::Environment Format =
3824 getContext().getObjectFileInfo()->getObjectFileType();
3825 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
3826 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00003827
Tim Northover3b0846e2014-05-24 12:50:23 +00003828 StringRef IDVal = DirectiveID.getIdentifier();
3829 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003830 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00003831 parseDirectiveArch(Loc);
3832 else if (IDVal == ".cpu")
3833 parseDirectiveCPU(Loc);
3834 else if (IDVal == ".hword")
3835 parseDirectiveWord(2, Loc);
3836 else if (IDVal == ".word")
3837 parseDirectiveWord(4, Loc);
3838 else if (IDVal == ".xword")
3839 parseDirectiveWord(8, Loc);
3840 else if (IDVal == ".tlsdesccall")
3841 parseDirectiveTLSDescCall(Loc);
3842 else if (IDVal == ".ltorg" || IDVal == ".pool")
3843 parseDirectiveLtorg(Loc);
3844 else if (IDVal == ".unreq")
3845 parseDirectiveUnreq(Loc);
3846 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00003847 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00003848 parseDirectiveInst(Loc);
3849 else
3850 return true;
3851 } else if (IDVal == MCLOHDirectiveName())
3852 parseDirectiveLOH(IDVal, Loc);
3853 else
3854 return true;
3855 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003856}
3857
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003858static const struct {
3859 const char *Name;
3860 const FeatureBitset Features;
3861} ExtensionMap[] = {
3862 { "crc", {AArch64::FeatureCRC} },
3863 { "crypto", {AArch64::FeatureCrypto} },
3864 { "fp", {AArch64::FeatureFPARMv8} },
3865 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003866 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00003867 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003868
3869 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003870 { "pan", {} },
3871 { "lor", {} },
3872 { "rdma", {} },
3873 { "profile", {} },
3874};
3875
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003876/// parseDirectiveArch
3877/// ::= .arch token
3878bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
3879 SMLoc ArchLoc = getLoc();
3880
3881 StringRef Arch, ExtensionString;
3882 std::tie(Arch, ExtensionString) =
3883 getParser().parseStringToEndOfStatement().trim().split('+');
3884
Florian Hahn67ddd1d2017-07-27 16:27:56 +00003885 AArch64::ArchKind ID = AArch64::parseArch(Arch);
3886 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00003887 return Error(ArchLoc, "unknown arch name");
3888
3889 if (parseToken(AsmToken::EndOfStatement))
3890 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003891
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003892 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00003893 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003894 AArch64::getArchFeatures(ID, AArch64Features);
3895 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
3896 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003897
Eric Christopher98ddbdb2016-09-08 17:27:03 +00003898 MCSubtargetInfo &STI = copySTI();
3899 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
3900 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
3901
3902 SmallVector<StringRef, 4> RequestedExtensions;
3903 if (!ExtensionString.empty())
3904 ExtensionString.split(RequestedExtensions, '+');
3905
3906 FeatureBitset Features = STI.getFeatureBits();
3907 for (auto Name : RequestedExtensions) {
3908 bool EnableFeature = true;
3909
3910 if (Name.startswith_lower("no")) {
3911 EnableFeature = false;
3912 Name = Name.substr(2);
3913 }
3914
3915 for (const auto &Extension : ExtensionMap) {
3916 if (Extension.Name != Name)
3917 continue;
3918
3919 if (Extension.Features.none())
3920 report_fatal_error("unsupported architectural extension: " + Name);
3921
3922 FeatureBitset ToggleFeatures = EnableFeature
3923 ? (~Features & Extension.Features)
3924 : ( Features & Extension.Features);
3925 uint64_t Features =
3926 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
3927 setAvailableFeatures(Features);
3928 break;
3929 }
3930 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00003931 return false;
3932}
3933
Tim Northover8b96c7e2017-05-15 19:42:15 +00003934static SMLoc incrementLoc(SMLoc L, int Offset) {
3935 return SMLoc::getFromPointer(L.getPointer() + Offset);
3936}
3937
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003938/// parseDirectiveCPU
3939/// ::= .cpu id
3940bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00003941 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003942
3943 StringRef CPU, ExtensionString;
3944 std::tie(CPU, ExtensionString) =
3945 getParser().parseStringToEndOfStatement().trim().split('+');
3946
Nirav Davee833c6c2016-11-08 18:31:04 +00003947 if (parseToken(AsmToken::EndOfStatement))
3948 return true;
3949
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003950 SmallVector<StringRef, 4> RequestedExtensions;
3951 if (!ExtensionString.empty())
3952 ExtensionString.split(RequestedExtensions, '+');
3953
3954 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
3955 // once that is tablegen'ed
3956 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00003957 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003958 return false;
3959 }
3960
3961 MCSubtargetInfo &STI = copySTI();
3962 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00003963 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003964
3965 FeatureBitset Features = STI.getFeatureBits();
3966 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00003967 // Advance source location past '+'.
3968 CurLoc = incrementLoc(CurLoc, 1);
3969
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003970 bool EnableFeature = true;
3971
3972 if (Name.startswith_lower("no")) {
3973 EnableFeature = false;
3974 Name = Name.substr(2);
3975 }
3976
Tim Northover8b96c7e2017-05-15 19:42:15 +00003977 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003978 for (const auto &Extension : ExtensionMap) {
3979 if (Extension.Name != Name)
3980 continue;
3981
3982 if (Extension.Features.none())
3983 report_fatal_error("unsupported architectural extension: " + Name);
3984
3985 FeatureBitset ToggleFeatures = EnableFeature
3986 ? (~Features & Extension.Features)
3987 : ( Features & Extension.Features);
3988 uint64_t Features =
3989 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
3990 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00003991 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00003992
3993 break;
3994 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00003995
3996 if (!FoundExtension)
3997 Error(CurLoc, "unsupported architectural extension");
3998
3999 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004000 }
4001 return false;
4002}
4003
Tim Northover3b0846e2014-05-24 12:50:23 +00004004/// parseDirectiveWord
4005/// ::= .word [ expression (, expression)* ]
4006bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004007 auto parseOp = [&]() -> bool {
4008 const MCExpr *Value;
4009 if (getParser().parseExpression(Value))
4010 return true;
4011 getParser().getStreamer().EmitValue(Value, Size, L);
4012 return false;
4013 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004014
Nirav Davee833c6c2016-11-08 18:31:04 +00004015 if (parseMany(parseOp))
4016 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004017 return false;
4018}
4019
Chad Rosierdcd2a302014-10-22 20:35:57 +00004020/// parseDirectiveInst
4021/// ::= .inst opcode [, ...]
4022bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004023 if (getLexer().is(AsmToken::EndOfStatement))
4024 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004025
Nirav Davee833c6c2016-11-08 18:31:04 +00004026 auto parseOp = [&]() -> bool {
4027 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004028 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004029 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4030 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004031 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004032 if (check(!Value, L, "expected constant expression"))
4033 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004034 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004035 return false;
4036 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004037
Nirav Davee833c6c2016-11-08 18:31:04 +00004038 if (parseMany(parseOp))
4039 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004040 return false;
4041}
4042
Tim Northover3b0846e2014-05-24 12:50:23 +00004043// parseDirectiveTLSDescCall:
4044// ::= .tlsdesccall symbol
4045bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4046 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004047 if (check(getParser().parseIdentifier(Name), L,
4048 "expected symbol after directive") ||
4049 parseToken(AsmToken::EndOfStatement))
4050 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004051
Jim Grosbach6f482002015-05-18 18:43:14 +00004052 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004053 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4054 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004055
4056 MCInst Inst;
4057 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004058 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004059
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004060 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004061 return false;
4062}
4063
4064/// ::= .loh <lohName | lohId> label1, ..., labelN
4065/// The number of arguments depends on the loh identifier.
4066bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004067 MCLOHType Kind;
4068 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4069 if (getParser().getTok().isNot(AsmToken::Integer))
4070 return TokError("expected an identifier or a number in directive");
4071 // We successfully get a numeric value for the identifier.
4072 // Check if it is valid.
4073 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004074 if (Id <= -1U && !isValidMCLOHType(Id))
4075 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004076 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004077 } else {
4078 StringRef Name = getTok().getIdentifier();
4079 // We successfully parse an identifier.
4080 // Check if it is a recognized one.
4081 int Id = MCLOHNameToId(Name);
4082
4083 if (Id == -1)
4084 return TokError("invalid identifier in directive");
4085 Kind = (MCLOHType)Id;
4086 }
4087 // Consume the identifier.
4088 Lex();
4089 // Get the number of arguments of this LOH.
4090 int NbArgs = MCLOHIdToNbArgs(Kind);
4091
4092 assert(NbArgs != -1 && "Invalid number of arguments");
4093
4094 SmallVector<MCSymbol *, 3> Args;
4095 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4096 StringRef Name;
4097 if (getParser().parseIdentifier(Name))
4098 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004099 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004100
4101 if (Idx + 1 == NbArgs)
4102 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004103 if (parseToken(AsmToken::Comma,
4104 "unexpected token in '" + Twine(IDVal) + "' directive"))
4105 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004106 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004107 if (parseToken(AsmToken::EndOfStatement,
4108 "unexpected token in '" + Twine(IDVal) + "' directive"))
4109 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004110
4111 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4112 return false;
4113}
4114
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004115/// parseDirectiveLtorg
4116/// ::= .ltorg | .pool
4117bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004118 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4119 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004120 getTargetStreamer().emitCurrentConstantPool();
4121 return false;
4122}
4123
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004124/// parseDirectiveReq
4125/// ::= name .req registername
4126bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004127 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004128 Parser.Lex(); // Eat the '.req' token.
4129 SMLoc SRegLoc = getLoc();
4130 unsigned RegNum = tryParseRegister();
4131 bool IsVector = false;
4132
4133 if (RegNum == static_cast<unsigned>(-1)) {
4134 StringRef Kind;
4135 RegNum = tryMatchVectorRegister(Kind, false);
Nirav Dave2364748a2016-09-16 18:30:20 +00004136 if (!Kind.empty())
4137 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004138 IsVector = true;
4139 }
4140
Nirav Dave2364748a2016-09-16 18:30:20 +00004141 if (RegNum == static_cast<unsigned>(-1))
4142 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004143
4144 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004145 if (parseToken(AsmToken::EndOfStatement,
4146 "unexpected input in .req directive"))
4147 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004148
4149 auto pair = std::make_pair(IsVector, RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004150 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004151 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4152
Nirav Dave2364748a2016-09-16 18:30:20 +00004153 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004154}
4155
4156/// parseDirectiveUneq
4157/// ::= .unreq registername
4158bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004159 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004160 if (getTok().isNot(AsmToken::Identifier))
4161 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004162 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4163 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004164 if (parseToken(AsmToken::EndOfStatement))
4165 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004166 return false;
4167}
4168
Tim Northover3b0846e2014-05-24 12:50:23 +00004169bool
4170AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4171 AArch64MCExpr::VariantKind &ELFRefKind,
4172 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4173 int64_t &Addend) {
4174 ELFRefKind = AArch64MCExpr::VK_INVALID;
4175 DarwinRefKind = MCSymbolRefExpr::VK_None;
4176 Addend = 0;
4177
4178 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4179 ELFRefKind = AE->getKind();
4180 Expr = AE->getSubExpr();
4181 }
4182
4183 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4184 if (SE) {
4185 // It's a simple symbol reference with no addend.
4186 DarwinRefKind = SE->getKind();
4187 return true;
4188 }
4189
4190 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4191 if (!BE)
4192 return false;
4193
4194 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4195 if (!SE)
4196 return false;
4197 DarwinRefKind = SE->getKind();
4198
4199 if (BE->getOpcode() != MCBinaryExpr::Add &&
4200 BE->getOpcode() != MCBinaryExpr::Sub)
4201 return false;
4202
4203 // See if the addend is is a constant, otherwise there's more going
4204 // on here than we can deal with.
4205 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4206 if (!AddendExpr)
4207 return false;
4208
4209 Addend = AddendExpr->getValue();
4210 if (BE->getOpcode() == MCBinaryExpr::Sub)
4211 Addend = -Addend;
4212
4213 // It's some symbol reference + a constant addend, but really
4214 // shouldn't use both Darwin and ELF syntax.
4215 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4216 DarwinRefKind == MCSymbolRefExpr::VK_None;
4217}
4218
4219/// Force static initialization.
4220extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004221 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4222 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4223 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004224}
4225
4226#define GET_REGISTER_MATCHER
4227#define GET_SUBTARGET_FEATURE_NAME
4228#define GET_MATCHER_IMPLEMENTATION
4229#include "AArch64GenAsmMatcher.inc"
4230
4231// Define this matcher function after the auto-generated include so we
4232// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004233unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004234 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004235 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004236 // If the kind is a token for a literal immediate, check if our asm
4237 // operand matches. This is for InstAliases which have a fixed-value
4238 // immediate in the syntax.
4239 int64_t ExpectedVal;
4240 switch (Kind) {
4241 default:
4242 return Match_InvalidOperand;
4243 case MCK__35_0:
4244 ExpectedVal = 0;
4245 break;
4246 case MCK__35_1:
4247 ExpectedVal = 1;
4248 break;
4249 case MCK__35_12:
4250 ExpectedVal = 12;
4251 break;
4252 case MCK__35_16:
4253 ExpectedVal = 16;
4254 break;
4255 case MCK__35_2:
4256 ExpectedVal = 2;
4257 break;
4258 case MCK__35_24:
4259 ExpectedVal = 24;
4260 break;
4261 case MCK__35_3:
4262 ExpectedVal = 3;
4263 break;
4264 case MCK__35_32:
4265 ExpectedVal = 32;
4266 break;
4267 case MCK__35_4:
4268 ExpectedVal = 4;
4269 break;
4270 case MCK__35_48:
4271 ExpectedVal = 48;
4272 break;
4273 case MCK__35_6:
4274 ExpectedVal = 6;
4275 break;
4276 case MCK__35_64:
4277 ExpectedVal = 64;
4278 break;
4279 case MCK__35_8:
4280 ExpectedVal = 8;
4281 break;
4282 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004283 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004284 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004285 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004286 if (!CE)
4287 return Match_InvalidOperand;
4288 if (CE->getValue() == ExpectedVal)
4289 return Match_Success;
4290 return Match_InvalidOperand;
4291}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004292
Alex Bradbury58eba092016-11-01 16:32:05 +00004293OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004294AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4295
4296 SMLoc S = getLoc();
4297
4298 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4299 Error(S, "expected register");
4300 return MatchOperand_ParseFail;
4301 }
4302
4303 int FirstReg = tryParseRegister();
4304 if (FirstReg == -1) {
4305 return MatchOperand_ParseFail;
4306 }
4307 const MCRegisterClass &WRegClass =
4308 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4309 const MCRegisterClass &XRegClass =
4310 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4311
4312 bool isXReg = XRegClass.contains(FirstReg),
4313 isWReg = WRegClass.contains(FirstReg);
4314 if (!isXReg && !isWReg) {
4315 Error(S, "expected first even register of a "
4316 "consecutive same-size even/odd register pair");
4317 return MatchOperand_ParseFail;
4318 }
4319
4320 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4321 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4322
4323 if (FirstEncoding & 0x1) {
4324 Error(S, "expected first even register of a "
4325 "consecutive same-size even/odd register pair");
4326 return MatchOperand_ParseFail;
4327 }
4328
4329 SMLoc M = getLoc();
4330 if (getParser().getTok().isNot(AsmToken::Comma)) {
4331 Error(M, "expected comma");
4332 return MatchOperand_ParseFail;
4333 }
4334 // Eat the comma
4335 getParser().Lex();
4336
4337 SMLoc E = getLoc();
4338 int SecondReg = tryParseRegister();
4339 if (SecondReg ==-1) {
4340 return MatchOperand_ParseFail;
4341 }
4342
Eugene Zelenko049b0172017-01-06 00:30:53 +00004343 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004344 (isXReg && !XRegClass.contains(SecondReg)) ||
4345 (isWReg && !WRegClass.contains(SecondReg))) {
4346 Error(E,"expected second odd register of a "
4347 "consecutive same-size even/odd register pair");
4348 return MatchOperand_ParseFail;
4349 }
Joel Jones504bf332016-10-24 13:37:13 +00004350
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004351 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004352 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004353 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4354 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4355 } else {
4356 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4357 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4358 }
4359
4360 Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4361 getContext()));
4362
4363 return MatchOperand_Success;
4364}