1 //==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "MCTargetDesc/AArch64AddressingModes.h"
10 #include "MCTargetDesc/AArch64InstPrinter.h"
11 #include "MCTargetDesc/AArch64MCExpr.h"
12 #include "MCTargetDesc/AArch64MCTargetDesc.h"
13 #include "MCTargetDesc/AArch64TargetStreamer.h"
14 #include "TargetInfo/AArch64TargetInfo.h"
15 #include "AArch64InstrInfo.h"
16 #include "Utils/AArch64BaseInfo.h"
17 #include "llvm/ADT/APFloat.h"
18 #include "llvm/ADT/APInt.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/SmallSet.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/StringExtras.h"
24 #include "llvm/ADT/StringMap.h"
25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/ADT/StringSwitch.h"
27 #include "llvm/ADT/Twine.h"
28 #include "llvm/MC/MCContext.h"
29 #include "llvm/MC/MCExpr.h"
30 #include "llvm/MC/MCInst.h"
31 #include "llvm/MC/MCLinkerOptimizationHint.h"
32 #include "llvm/MC/MCObjectFileInfo.h"
33 #include "llvm/MC/MCParser/MCAsmLexer.h"
34 #include "llvm/MC/MCParser/MCAsmParser.h"
35 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
36 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
37 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
38 #include "llvm/MC/MCRegisterInfo.h"
39 #include "llvm/MC/MCStreamer.h"
40 #include "llvm/MC/MCSubtargetInfo.h"
41 #include "llvm/MC/MCSymbol.h"
42 #include "llvm/MC/MCTargetOptions.h"
43 #include "llvm/MC/SubtargetFeature.h"
44 #include "llvm/MC/MCValue.h"
45 #include "llvm/Support/Casting.h"
46 #include "llvm/Support/Compiler.h"
47 #include "llvm/Support/ErrorHandling.h"
48 #include "llvm/Support/MathExtras.h"
49 #include "llvm/Support/SMLoc.h"
50 #include "llvm/Support/TargetParser.h"
51 #include "llvm/Support/TargetRegistry.h"
52 #include "llvm/Support/raw_ostream.h"
74 enum class MatrixKind
{ Array
, Tile
, Row
, Col
};
76 enum RegConstraintEqualityTy
{
82 class AArch64AsmParser
: public MCTargetAsmParser
{
84 StringRef Mnemonic
; ///< Instruction mnemonic.
86 // Map of register aliases registers via the .req directive.
87 StringMap
<std::pair
<RegKind
, unsigned>> RegisterReqs
;
91 static PrefixInfo
CreateFromInst(const MCInst
&Inst
, uint64_t TSFlags
) {
93 switch (Inst
.getOpcode()) {
94 case AArch64::MOVPRFX_ZZ
:
96 Prefix
.Dst
= Inst
.getOperand(0).getReg();
98 case AArch64::MOVPRFX_ZPmZ_B
:
99 case AArch64::MOVPRFX_ZPmZ_H
:
100 case AArch64::MOVPRFX_ZPmZ_S
:
101 case AArch64::MOVPRFX_ZPmZ_D
:
102 Prefix
.Active
= true;
103 Prefix
.Predicated
= true;
104 Prefix
.ElementSize
= TSFlags
& AArch64::ElementSizeMask
;
105 assert(Prefix
.ElementSize
!= AArch64::ElementSizeNone
&&
106 "No destructive element size set for movprfx");
107 Prefix
.Dst
= Inst
.getOperand(0).getReg();
108 Prefix
.Pg
= Inst
.getOperand(2).getReg();
110 case AArch64::MOVPRFX_ZPzZ_B
:
111 case AArch64::MOVPRFX_ZPzZ_H
:
112 case AArch64::MOVPRFX_ZPzZ_S
:
113 case AArch64::MOVPRFX_ZPzZ_D
:
114 Prefix
.Active
= true;
115 Prefix
.Predicated
= true;
116 Prefix
.ElementSize
= TSFlags
& AArch64::ElementSizeMask
;
117 assert(Prefix
.ElementSize
!= AArch64::ElementSizeNone
&&
118 "No destructive element size set for movprfx");
119 Prefix
.Dst
= Inst
.getOperand(0).getReg();
120 Prefix
.Pg
= Inst
.getOperand(1).getReg();
129 PrefixInfo() : Active(false), Predicated(false) {}
130 bool isActive() const { return Active
; }
131 bool isPredicated() const { return Predicated
; }
132 unsigned getElementSize() const {
136 unsigned getDstReg() const { return Dst
; }
137 unsigned getPgReg() const {
145 unsigned ElementSize
;
150 AArch64TargetStreamer
&getTargetStreamer() {
151 MCTargetStreamer
&TS
= *getParser().getStreamer().getTargetStreamer();
152 return static_cast<AArch64TargetStreamer
&>(TS
);
155 SMLoc
getLoc() const { return getParser().getTok().getLoc(); }
157 bool parseSysAlias(StringRef Name
, SMLoc NameLoc
, OperandVector
&Operands
);
158 void createSysAlias(uint16_t Encoding
, OperandVector
&Operands
, SMLoc S
);
159 AArch64CC::CondCode
parseCondCodeString(StringRef Cond
);
160 bool parseCondCode(OperandVector
&Operands
, bool invertCondCode
);
161 unsigned matchRegisterNameAlias(StringRef Name
, RegKind Kind
);
162 bool parseRegister(OperandVector
&Operands
);
163 bool parseSymbolicImmVal(const MCExpr
*&ImmVal
);
164 bool parseNeonVectorList(OperandVector
&Operands
);
165 bool parseOptionalMulOperand(OperandVector
&Operands
);
166 bool parseKeywordOperand(OperandVector
&Operands
);
167 bool parseOperand(OperandVector
&Operands
, bool isCondCode
,
168 bool invertCondCode
);
169 bool parseImmExpr(int64_t &Out
);
171 bool parseRegisterInRange(unsigned &Out
, unsigned Base
, unsigned First
,
174 bool showMatchError(SMLoc Loc
, unsigned ErrCode
, uint64_t ErrorInfo
,
175 OperandVector
&Operands
);
177 bool parseDirectiveArch(SMLoc L
);
178 bool parseDirectiveArchExtension(SMLoc L
);
179 bool parseDirectiveCPU(SMLoc L
);
180 bool parseDirectiveInst(SMLoc L
);
182 bool parseDirectiveTLSDescCall(SMLoc L
);
184 bool parseDirectiveLOH(StringRef LOH
, SMLoc L
);
185 bool parseDirectiveLtorg(SMLoc L
);
187 bool parseDirectiveReq(StringRef Name
, SMLoc L
);
188 bool parseDirectiveUnreq(SMLoc L
);
189 bool parseDirectiveCFINegateRAState();
190 bool parseDirectiveCFIBKeyFrame();
192 bool parseDirectiveVariantPCS(SMLoc L
);
194 bool parseDirectiveSEHAllocStack(SMLoc L
);
195 bool parseDirectiveSEHPrologEnd(SMLoc L
);
196 bool parseDirectiveSEHSaveR19R20X(SMLoc L
);
197 bool parseDirectiveSEHSaveFPLR(SMLoc L
);
198 bool parseDirectiveSEHSaveFPLRX(SMLoc L
);
199 bool parseDirectiveSEHSaveReg(SMLoc L
);
200 bool parseDirectiveSEHSaveRegX(SMLoc L
);
201 bool parseDirectiveSEHSaveRegP(SMLoc L
);
202 bool parseDirectiveSEHSaveRegPX(SMLoc L
);
203 bool parseDirectiveSEHSaveLRPair(SMLoc L
);
204 bool parseDirectiveSEHSaveFReg(SMLoc L
);
205 bool parseDirectiveSEHSaveFRegX(SMLoc L
);
206 bool parseDirectiveSEHSaveFRegP(SMLoc L
);
207 bool parseDirectiveSEHSaveFRegPX(SMLoc L
);
208 bool parseDirectiveSEHSetFP(SMLoc L
);
209 bool parseDirectiveSEHAddFP(SMLoc L
);
210 bool parseDirectiveSEHNop(SMLoc L
);
211 bool parseDirectiveSEHSaveNext(SMLoc L
);
212 bool parseDirectiveSEHEpilogStart(SMLoc L
);
213 bool parseDirectiveSEHEpilogEnd(SMLoc L
);
214 bool parseDirectiveSEHTrapFrame(SMLoc L
);
215 bool parseDirectiveSEHMachineFrame(SMLoc L
);
216 bool parseDirectiveSEHContext(SMLoc L
);
217 bool parseDirectiveSEHClearUnwoundToCall(SMLoc L
);
219 bool validateInstruction(MCInst
&Inst
, SMLoc
&IDLoc
,
220 SmallVectorImpl
<SMLoc
> &Loc
);
221 bool MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
222 OperandVector
&Operands
, MCStreamer
&Out
,
224 bool MatchingInlineAsm
) override
;
225 /// @name Auto-generated Match Functions
228 #define GET_ASSEMBLER_HEADER
229 #include "AArch64GenAsmMatcher.inc"
233 OperandMatchResultTy
tryParseScalarRegister(unsigned &Reg
);
234 OperandMatchResultTy
tryParseVectorRegister(unsigned &Reg
, StringRef
&Kind
,
236 OperandMatchResultTy
tryParseMatrixRegister(OperandVector
&Operands
);
237 OperandMatchResultTy
tryParseSVCR(OperandVector
&Operands
);
238 OperandMatchResultTy
tryParseOptionalShiftExtend(OperandVector
&Operands
);
239 OperandMatchResultTy
tryParseBarrierOperand(OperandVector
&Operands
);
240 OperandMatchResultTy
tryParseBarriernXSOperand(OperandVector
&Operands
);
241 OperandMatchResultTy
tryParseMRSSystemRegister(OperandVector
&Operands
);
242 OperandMatchResultTy
tryParseSysReg(OperandVector
&Operands
);
243 OperandMatchResultTy
tryParseSysCROperand(OperandVector
&Operands
);
244 template <bool IsSVEPrefetch
= false>
245 OperandMatchResultTy
tryParsePrefetch(OperandVector
&Operands
);
246 OperandMatchResultTy
tryParsePSBHint(OperandVector
&Operands
);
247 OperandMatchResultTy
tryParseBTIHint(OperandVector
&Operands
);
248 OperandMatchResultTy
tryParseAdrpLabel(OperandVector
&Operands
);
249 OperandMatchResultTy
tryParseAdrLabel(OperandVector
&Operands
);
250 template<bool AddFPZeroAsLiteral
>
251 OperandMatchResultTy
tryParseFPImm(OperandVector
&Operands
);
252 OperandMatchResultTy
tryParseImmWithOptionalShift(OperandVector
&Operands
);
253 OperandMatchResultTy
tryParseGPR64sp0Operand(OperandVector
&Operands
);
254 bool tryParseNeonVectorRegister(OperandVector
&Operands
);
255 OperandMatchResultTy
tryParseVectorIndex(OperandVector
&Operands
);
256 OperandMatchResultTy
tryParseGPRSeqPair(OperandVector
&Operands
);
257 template <bool ParseShiftExtend
,
258 RegConstraintEqualityTy EqTy
= RegConstraintEqualityTy::EqualsReg
>
259 OperandMatchResultTy
tryParseGPROperand(OperandVector
&Operands
);
260 template <bool ParseShiftExtend
, bool ParseSuffix
>
261 OperandMatchResultTy
tryParseSVEDataVector(OperandVector
&Operands
);
262 OperandMatchResultTy
tryParseSVEPredicateVector(OperandVector
&Operands
);
263 template <RegKind VectorKind
>
264 OperandMatchResultTy
tryParseVectorList(OperandVector
&Operands
,
265 bool ExpectMatch
= false);
266 OperandMatchResultTy
tryParseMatrixTileList(OperandVector
&Operands
);
267 OperandMatchResultTy
tryParseSVEPattern(OperandVector
&Operands
);
268 OperandMatchResultTy
tryParseGPR64x8(OperandVector
&Operands
);
271 enum AArch64MatchResultTy
{
272 Match_InvalidSuffix
= FIRST_TARGET_MATCH_RESULT_TY
,
273 #define GET_OPERAND_DIAGNOSTIC_TYPES
274 #include "AArch64GenAsmMatcher.inc"
278 AArch64AsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
279 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
280 : MCTargetAsmParser(Options
, STI
, MII
) {
281 IsILP32
= STI
.getTargetTriple().getEnvironment() == Triple::GNUILP32
;
282 MCAsmParserExtension::Initialize(Parser
);
283 MCStreamer
&S
= getParser().getStreamer();
284 if (S
.getTargetStreamer() == nullptr)
285 new AArch64TargetStreamer(S
);
287 // Alias .hword/.word/.[dx]word to the target-independent
288 // .2byte/.4byte/.8byte directives as they have the same form and
290 /// ::= (.hword | .word | .dword | .xword ) [ expression (, expression)* ]
291 Parser
.addAliasForDirective(".hword", ".2byte");
292 Parser
.addAliasForDirective(".word", ".4byte");
293 Parser
.addAliasForDirective(".dword", ".8byte");
294 Parser
.addAliasForDirective(".xword", ".8byte");
296 // Initialize the set of available features.
297 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
300 bool regsEqual(const MCParsedAsmOperand
&Op1
,
301 const MCParsedAsmOperand
&Op2
) const override
;
302 bool ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
303 SMLoc NameLoc
, OperandVector
&Operands
) override
;
304 bool ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
305 OperandMatchResultTy
tryParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
,
306 SMLoc
&EndLoc
) override
;
307 bool ParseDirective(AsmToken DirectiveID
) override
;
308 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
309 unsigned Kind
) override
;
311 static bool classifySymbolRef(const MCExpr
*Expr
,
312 AArch64MCExpr::VariantKind
&ELFRefKind
,
313 MCSymbolRefExpr::VariantKind
&DarwinRefKind
,
317 /// AArch64Operand - Instances of this class represent a parsed AArch64 machine
319 class AArch64Operand
: public MCParsedAsmOperand
{
342 SMLoc StartLoc
, EndLoc
;
347 bool IsSuffix
; // Is the operand actually a suffix on the mnemonic.
350 // Separate shift/extend operand.
351 struct ShiftExtendOp
{
352 AArch64_AM::ShiftExtendType Type
;
354 bool HasExplicitAmount
;
362 // The register may be allowed as a different register class,
363 // e.g. for GPR64as32 or GPR32as64.
364 RegConstraintEqualityTy EqualityTy
;
366 // In some cases the shift/extend needs to be explicitly parsed together
367 // with the register, rather than as a separate operand. This is needed
368 // for addressing modes where the instruction as a whole dictates the
369 // scaling/extend, rather than specific bits in the instruction.
370 // By parsing them as a single operand, we avoid the need to pass an
371 // extra operand in all CodeGen patterns (because all operands need to
372 // have an associated value), and we avoid the need to update TableGen to
373 // accept operands that have no associated bits in the instruction.
375 // An added benefit of parsing them together is that the assembler
376 // can give a sensible diagnostic if the scaling is not correct.
378 // The default is 'lsl #0' (HasExplicitAmount = false) if no
379 // ShiftExtend is specified.
380 ShiftExtendOp ShiftExtend
;
385 unsigned ElementWidth
;
389 struct MatrixTileListOp
{
390 unsigned RegMask
= 0;
393 struct VectorListOp
{
396 unsigned NumElements
;
397 unsigned ElementWidth
;
398 RegKind RegisterKind
;
401 struct VectorIndexOp
{
409 struct ShiftedImmOp
{
411 unsigned ShiftAmount
;
415 AArch64CC::CondCode Code
;
419 uint64_t Val
; // APFloat value bitcasted to uint64_t.
420 bool IsExact
; // describes whether parsed value was exact.
426 unsigned Val
; // Not the enum since not all values have names.
435 uint32_t PStateField
;
463 unsigned PStateField
;
469 struct MatrixRegOp MatrixReg
;
470 struct MatrixTileListOp MatrixTileList
;
471 struct VectorListOp VectorList
;
472 struct VectorIndexOp VectorIndex
;
474 struct ShiftedImmOp ShiftedImm
;
475 struct CondCodeOp CondCode
;
476 struct FPImmOp FPImm
;
477 struct BarrierOp Barrier
;
478 struct SysRegOp SysReg
;
479 struct SysCRImmOp SysCRImm
;
480 struct PrefetchOp Prefetch
;
481 struct PSBHintOp PSBHint
;
482 struct BTIHintOp BTIHint
;
483 struct ShiftExtendOp ShiftExtend
;
487 // Keep the MCContext around as the MCExprs may need manipulated during
488 // the add<>Operands() calls.
492 AArch64Operand(KindTy K
, MCContext
&Ctx
) : Kind(K
), Ctx(Ctx
) {}
494 AArch64Operand(const AArch64Operand
&o
) : MCParsedAsmOperand(), Ctx(o
.Ctx
) {
496 StartLoc
= o
.StartLoc
;
506 ShiftedImm
= o
.ShiftedImm
;
509 CondCode
= o
.CondCode
;
520 case k_MatrixRegister
:
521 MatrixReg
= o
.MatrixReg
;
523 case k_MatrixTileList
:
524 MatrixTileList
= o
.MatrixTileList
;
527 VectorList
= o
.VectorList
;
530 VectorIndex
= o
.VectorIndex
;
536 SysCRImm
= o
.SysCRImm
;
539 Prefetch
= o
.Prefetch
;
548 ShiftExtend
= o
.ShiftExtend
;
556 /// getStartLoc - Get the location of the first token of this operand.
557 SMLoc
getStartLoc() const override
{ return StartLoc
; }
558 /// getEndLoc - Get the location of the last token of this operand.
559 SMLoc
getEndLoc() const override
{ return EndLoc
; }
561 StringRef
getToken() const {
562 assert(Kind
== k_Token
&& "Invalid access!");
563 return StringRef(Tok
.Data
, Tok
.Length
);
566 bool isTokenSuffix() const {
567 assert(Kind
== k_Token
&& "Invalid access!");
571 const MCExpr
*getImm() const {
572 assert(Kind
== k_Immediate
&& "Invalid access!");
576 const MCExpr
*getShiftedImmVal() const {
577 assert(Kind
== k_ShiftedImm
&& "Invalid access!");
578 return ShiftedImm
.Val
;
581 unsigned getShiftedImmShift() const {
582 assert(Kind
== k_ShiftedImm
&& "Invalid access!");
583 return ShiftedImm
.ShiftAmount
;
586 AArch64CC::CondCode
getCondCode() const {
587 assert(Kind
== k_CondCode
&& "Invalid access!");
588 return CondCode
.Code
;
591 APFloat
getFPImm() const {
592 assert (Kind
== k_FPImm
&& "Invalid access!");
593 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm
.Val
, true));
596 bool getFPImmIsExact() const {
597 assert (Kind
== k_FPImm
&& "Invalid access!");
598 return FPImm
.IsExact
;
601 unsigned getBarrier() const {
602 assert(Kind
== k_Barrier
&& "Invalid access!");
606 StringRef
getBarrierName() const {
607 assert(Kind
== k_Barrier
&& "Invalid access!");
608 return StringRef(Barrier
.Data
, Barrier
.Length
);
611 bool getBarriernXSModifier() const {
612 assert(Kind
== k_Barrier
&& "Invalid access!");
613 return Barrier
.HasnXSModifier
;
616 unsigned getReg() const override
{
617 assert(Kind
== k_Register
&& "Invalid access!");
621 unsigned getMatrixReg() const {
622 assert(Kind
== k_MatrixRegister
&& "Invalid access!");
623 return MatrixReg
.RegNum
;
626 unsigned getMatrixElementWidth() const {
627 assert(Kind
== k_MatrixRegister
&& "Invalid access!");
628 return MatrixReg
.ElementWidth
;
631 MatrixKind
getMatrixKind() const {
632 assert(Kind
== k_MatrixRegister
&& "Invalid access!");
633 return MatrixReg
.Kind
;
636 unsigned getMatrixTileListRegMask() const {
637 assert(isMatrixTileList() && "Invalid access!");
638 return MatrixTileList
.RegMask
;
641 RegConstraintEqualityTy
getRegEqualityTy() const {
642 assert(Kind
== k_Register
&& "Invalid access!");
643 return Reg
.EqualityTy
;
646 unsigned getVectorListStart() const {
647 assert(Kind
== k_VectorList
&& "Invalid access!");
648 return VectorList
.RegNum
;
651 unsigned getVectorListCount() const {
652 assert(Kind
== k_VectorList
&& "Invalid access!");
653 return VectorList
.Count
;
656 int getVectorIndex() const {
657 assert(Kind
== k_VectorIndex
&& "Invalid access!");
658 return VectorIndex
.Val
;
661 StringRef
getSysReg() const {
662 assert(Kind
== k_SysReg
&& "Invalid access!");
663 return StringRef(SysReg
.Data
, SysReg
.Length
);
666 unsigned getSysCR() const {
667 assert(Kind
== k_SysCR
&& "Invalid access!");
671 unsigned getPrefetch() const {
672 assert(Kind
== k_Prefetch
&& "Invalid access!");
676 unsigned getPSBHint() const {
677 assert(Kind
== k_PSBHint
&& "Invalid access!");
681 StringRef
getPSBHintName() const {
682 assert(Kind
== k_PSBHint
&& "Invalid access!");
683 return StringRef(PSBHint
.Data
, PSBHint
.Length
);
686 unsigned getBTIHint() const {
687 assert(Kind
== k_BTIHint
&& "Invalid access!");
691 StringRef
getBTIHintName() const {
692 assert(Kind
== k_BTIHint
&& "Invalid access!");
693 return StringRef(BTIHint
.Data
, BTIHint
.Length
);
696 StringRef
getSVCR() const {
697 assert(Kind
== k_SVCR
&& "Invalid access!");
698 return StringRef(SVCR
.Data
, SVCR
.Length
);
701 StringRef
getPrefetchName() const {
702 assert(Kind
== k_Prefetch
&& "Invalid access!");
703 return StringRef(Prefetch
.Data
, Prefetch
.Length
);
706 AArch64_AM::ShiftExtendType
getShiftExtendType() const {
707 if (Kind
== k_ShiftExtend
)
708 return ShiftExtend
.Type
;
709 if (Kind
== k_Register
)
710 return Reg
.ShiftExtend
.Type
;
711 llvm_unreachable("Invalid access!");
714 unsigned getShiftExtendAmount() const {
715 if (Kind
== k_ShiftExtend
)
716 return ShiftExtend
.Amount
;
717 if (Kind
== k_Register
)
718 return Reg
.ShiftExtend
.Amount
;
719 llvm_unreachable("Invalid access!");
722 bool hasShiftExtendAmount() const {
723 if (Kind
== k_ShiftExtend
)
724 return ShiftExtend
.HasExplicitAmount
;
725 if (Kind
== k_Register
)
726 return Reg
.ShiftExtend
.HasExplicitAmount
;
727 llvm_unreachable("Invalid access!");
730 bool isImm() const override
{ return Kind
== k_Immediate
; }
731 bool isMem() const override
{ return false; }
733 bool isUImm6() const {
736 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
739 int64_t Val
= MCE
->getValue();
740 return (Val
>= 0 && Val
< 64);
743 template <int Width
> bool isSImm() const { return isSImmScaled
<Width
, 1>(); }
745 template <int Bits
, int Scale
> DiagnosticPredicate
isSImmScaled() const {
746 return isImmScaled
<Bits
, Scale
>(true);
749 template <int Bits
, int Scale
> DiagnosticPredicate
isUImmScaled() const {
750 return isImmScaled
<Bits
, Scale
>(false);
753 template <int Bits
, int Scale
>
754 DiagnosticPredicate
isImmScaled(bool Signed
) const {
756 return DiagnosticPredicateTy::NoMatch
;
758 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
760 return DiagnosticPredicateTy::NoMatch
;
762 int64_t MinVal
, MaxVal
;
764 int64_t Shift
= Bits
- 1;
765 MinVal
= (int64_t(1) << Shift
) * -Scale
;
766 MaxVal
= ((int64_t(1) << Shift
) - 1) * Scale
;
769 MaxVal
= ((int64_t(1) << Bits
) - 1) * Scale
;
772 int64_t Val
= MCE
->getValue();
773 if (Val
>= MinVal
&& Val
<= MaxVal
&& (Val
% Scale
) == 0)
774 return DiagnosticPredicateTy::Match
;
776 return DiagnosticPredicateTy::NearMatch
;
779 DiagnosticPredicate
isSVEPattern() const {
781 return DiagnosticPredicateTy::NoMatch
;
782 auto *MCE
= dyn_cast
<MCConstantExpr
>(getImm());
784 return DiagnosticPredicateTy::NoMatch
;
785 int64_t Val
= MCE
->getValue();
786 if (Val
>= 0 && Val
< 32)
787 return DiagnosticPredicateTy::Match
;
788 return DiagnosticPredicateTy::NearMatch
;
791 bool isSymbolicUImm12Offset(const MCExpr
*Expr
) const {
792 AArch64MCExpr::VariantKind ELFRefKind
;
793 MCSymbolRefExpr::VariantKind DarwinRefKind
;
795 if (!AArch64AsmParser::classifySymbolRef(Expr
, ELFRefKind
, DarwinRefKind
,
797 // If we don't understand the expression, assume the best and
798 // let the fixup and relocation code deal with it.
802 if (DarwinRefKind
== MCSymbolRefExpr::VK_PAGEOFF
||
803 ELFRefKind
== AArch64MCExpr::VK_LO12
||
804 ELFRefKind
== AArch64MCExpr::VK_GOT_LO12
||
805 ELFRefKind
== AArch64MCExpr::VK_DTPREL_LO12
||
806 ELFRefKind
== AArch64MCExpr::VK_DTPREL_LO12_NC
||
807 ELFRefKind
== AArch64MCExpr::VK_TPREL_LO12
||
808 ELFRefKind
== AArch64MCExpr::VK_TPREL_LO12_NC
||
809 ELFRefKind
== AArch64MCExpr::VK_GOTTPREL_LO12_NC
||
810 ELFRefKind
== AArch64MCExpr::VK_TLSDESC_LO12
||
811 ELFRefKind
== AArch64MCExpr::VK_SECREL_LO12
||
812 ELFRefKind
== AArch64MCExpr::VK_SECREL_HI12
||
813 ELFRefKind
== AArch64MCExpr::VK_GOT_PAGE_LO15
) {
814 // Note that we don't range-check the addend. It's adjusted modulo page
815 // size when converted, so there is no "out of range" condition when using
818 } else if (DarwinRefKind
== MCSymbolRefExpr::VK_GOTPAGEOFF
||
819 DarwinRefKind
== MCSymbolRefExpr::VK_TLVPPAGEOFF
) {
820 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
827 template <int Scale
> bool isUImm12Offset() const {
831 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
833 return isSymbolicUImm12Offset(getImm());
835 int64_t Val
= MCE
->getValue();
836 return (Val
% Scale
) == 0 && Val
>= 0 && (Val
/ Scale
) < 0x1000;
839 template <int N
, int M
>
840 bool isImmInRange() const {
843 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
846 int64_t Val
= MCE
->getValue();
847 return (Val
>= N
&& Val
<= M
);
850 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
851 // a logical immediate can always be represented when inverted.
852 template <typename T
>
853 bool isLogicalImm() const {
856 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
860 int64_t Val
= MCE
->getValue();
861 // Avoid left shift by 64 directly.
862 uint64_t Upper
= UINT64_C(-1) << (sizeof(T
) * 4) << (sizeof(T
) * 4);
863 // Allow all-0 or all-1 in top bits to permit bitwise NOT.
864 if ((Val
& Upper
) && (Val
& Upper
) != Upper
)
867 return AArch64_AM::isLogicalImmediate(Val
& ~Upper
, sizeof(T
) * 8);
870 bool isShiftedImm() const { return Kind
== k_ShiftedImm
; }
872 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
873 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
874 /// immediate that can be shifted by 'Shift'.
875 template <unsigned Width
>
876 Optional
<std::pair
<int64_t, unsigned> > getShiftedVal() const {
877 if (isShiftedImm() && Width
== getShiftedImmShift())
878 if (auto *CE
= dyn_cast
<MCConstantExpr
>(getShiftedImmVal()))
879 return std::make_pair(CE
->getValue(), Width
);
882 if (auto *CE
= dyn_cast
<MCConstantExpr
>(getImm())) {
883 int64_t Val
= CE
->getValue();
884 if ((Val
!= 0) && (uint64_t(Val
>> Width
) << Width
) == uint64_t(Val
))
885 return std::make_pair(Val
>> Width
, Width
);
887 return std::make_pair(Val
, 0u);
893 bool isAddSubImm() const {
894 if (!isShiftedImm() && !isImm())
899 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
900 if (isShiftedImm()) {
901 unsigned Shift
= ShiftedImm
.ShiftAmount
;
902 Expr
= ShiftedImm
.Val
;
903 if (Shift
!= 0 && Shift
!= 12)
909 AArch64MCExpr::VariantKind ELFRefKind
;
910 MCSymbolRefExpr::VariantKind DarwinRefKind
;
912 if (AArch64AsmParser::classifySymbolRef(Expr
, ELFRefKind
,
913 DarwinRefKind
, Addend
)) {
914 return DarwinRefKind
== MCSymbolRefExpr::VK_PAGEOFF
915 || DarwinRefKind
== MCSymbolRefExpr::VK_TLVPPAGEOFF
916 || (DarwinRefKind
== MCSymbolRefExpr::VK_GOTPAGEOFF
&& Addend
== 0)
917 || ELFRefKind
== AArch64MCExpr::VK_LO12
918 || ELFRefKind
== AArch64MCExpr::VK_DTPREL_HI12
919 || ELFRefKind
== AArch64MCExpr::VK_DTPREL_LO12
920 || ELFRefKind
== AArch64MCExpr::VK_DTPREL_LO12_NC
921 || ELFRefKind
== AArch64MCExpr::VK_TPREL_HI12
922 || ELFRefKind
== AArch64MCExpr::VK_TPREL_LO12
923 || ELFRefKind
== AArch64MCExpr::VK_TPREL_LO12_NC
924 || ELFRefKind
== AArch64MCExpr::VK_TLSDESC_LO12
925 || ELFRefKind
== AArch64MCExpr::VK_SECREL_HI12
926 || ELFRefKind
== AArch64MCExpr::VK_SECREL_LO12
;
929 // If it's a constant, it should be a real immediate in range.
930 if (auto ShiftedVal
= getShiftedVal
<12>())
931 return ShiftedVal
->first
>= 0 && ShiftedVal
->first
<= 0xfff;
933 // If it's an expression, we hope for the best and let the fixup/relocation
934 // code deal with it.
938 bool isAddSubImmNeg() const {
939 if (!isShiftedImm() && !isImm())
942 // Otherwise it should be a real negative immediate in range.
943 if (auto ShiftedVal
= getShiftedVal
<12>())
944 return ShiftedVal
->first
< 0 && -ShiftedVal
->first
<= 0xfff;
949 // Signed value in the range -128 to +127. For element widths of
950 // 16 bits or higher it may also be a signed multiple of 256 in the
951 // range -32768 to +32512.
952 // For element-width of 8 bits a range of -128 to 255 is accepted,
953 // since a copy of a byte can be either signed/unsigned.
954 template <typename T
>
955 DiagnosticPredicate
isSVECpyImm() const {
956 if (!isShiftedImm() && (!isImm() || !isa
<MCConstantExpr
>(getImm())))
957 return DiagnosticPredicateTy::NoMatch
;
959 bool IsByte
= std::is_same
<int8_t, std::make_signed_t
<T
>>::value
||
960 std::is_same
<int8_t, T
>::value
;
961 if (auto ShiftedImm
= getShiftedVal
<8>())
962 if (!(IsByte
&& ShiftedImm
->second
) &&
963 AArch64_AM::isSVECpyImm
<T
>(uint64_t(ShiftedImm
->first
)
964 << ShiftedImm
->second
))
965 return DiagnosticPredicateTy::Match
;
967 return DiagnosticPredicateTy::NearMatch
;
970 // Unsigned value in the range 0 to 255. For element widths of
971 // 16 bits or higher it may also be a signed multiple of 256 in the
973 template <typename T
> DiagnosticPredicate
isSVEAddSubImm() const {
974 if (!isShiftedImm() && (!isImm() || !isa
<MCConstantExpr
>(getImm())))
975 return DiagnosticPredicateTy::NoMatch
;
977 bool IsByte
= std::is_same
<int8_t, std::make_signed_t
<T
>>::value
||
978 std::is_same
<int8_t, T
>::value
;
979 if (auto ShiftedImm
= getShiftedVal
<8>())
980 if (!(IsByte
&& ShiftedImm
->second
) &&
981 AArch64_AM::isSVEAddSubImm
<T
>(ShiftedImm
->first
982 << ShiftedImm
->second
))
983 return DiagnosticPredicateTy::Match
;
985 return DiagnosticPredicateTy::NearMatch
;
988 template <typename T
> DiagnosticPredicate
isSVEPreferredLogicalImm() const {
989 if (isLogicalImm
<T
>() && !isSVECpyImm
<T
>())
990 return DiagnosticPredicateTy::Match
;
991 return DiagnosticPredicateTy::NoMatch
;
994 bool isCondCode() const { return Kind
== k_CondCode
; }
996 bool isSIMDImmType10() const {
999 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
1002 return AArch64_AM::isAdvSIMDModImmType10(MCE
->getValue());
1006 bool isBranchTarget() const {
1009 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
1012 int64_t Val
= MCE
->getValue();
1015 assert(N
> 0 && "Branch target immediate cannot be 0 bits!");
1016 return (Val
>= -((1<<(N
-1)) << 2) && Val
<= (((1<<(N
-1))-1) << 2));
1020 isMovWSymbol(ArrayRef
<AArch64MCExpr::VariantKind
> AllowedModifiers
) const {
1024 AArch64MCExpr::VariantKind ELFRefKind
;
1025 MCSymbolRefExpr::VariantKind DarwinRefKind
;
1027 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind
,
1028 DarwinRefKind
, Addend
)) {
1031 if (DarwinRefKind
!= MCSymbolRefExpr::VK_None
)
1034 for (unsigned i
= 0; i
!= AllowedModifiers
.size(); ++i
) {
1035 if (ELFRefKind
== AllowedModifiers
[i
])
1042 bool isMovWSymbolG3() const {
1043 return isMovWSymbol({AArch64MCExpr::VK_ABS_G3
, AArch64MCExpr::VK_PREL_G3
});
1046 bool isMovWSymbolG2() const {
1047 return isMovWSymbol(
1048 {AArch64MCExpr::VK_ABS_G2
, AArch64MCExpr::VK_ABS_G2_S
,
1049 AArch64MCExpr::VK_ABS_G2_NC
, AArch64MCExpr::VK_PREL_G2
,
1050 AArch64MCExpr::VK_PREL_G2_NC
, AArch64MCExpr::VK_TPREL_G2
,
1051 AArch64MCExpr::VK_DTPREL_G2
});
1054 bool isMovWSymbolG1() const {
1055 return isMovWSymbol(
1056 {AArch64MCExpr::VK_ABS_G1
, AArch64MCExpr::VK_ABS_G1_S
,
1057 AArch64MCExpr::VK_ABS_G1_NC
, AArch64MCExpr::VK_PREL_G1
,
1058 AArch64MCExpr::VK_PREL_G1_NC
, AArch64MCExpr::VK_GOTTPREL_G1
,
1059 AArch64MCExpr::VK_TPREL_G1
, AArch64MCExpr::VK_TPREL_G1_NC
,
1060 AArch64MCExpr::VK_DTPREL_G1
, AArch64MCExpr::VK_DTPREL_G1_NC
});
1063 bool isMovWSymbolG0() const {
1064 return isMovWSymbol(
1065 {AArch64MCExpr::VK_ABS_G0
, AArch64MCExpr::VK_ABS_G0_S
,
1066 AArch64MCExpr::VK_ABS_G0_NC
, AArch64MCExpr::VK_PREL_G0
,
1067 AArch64MCExpr::VK_PREL_G0_NC
, AArch64MCExpr::VK_GOTTPREL_G0_NC
,
1068 AArch64MCExpr::VK_TPREL_G0
, AArch64MCExpr::VK_TPREL_G0_NC
,
1069 AArch64MCExpr::VK_DTPREL_G0
, AArch64MCExpr::VK_DTPREL_G0_NC
});
1072 template<int RegWidth
, int Shift
>
1073 bool isMOVZMovAlias() const {
1074 if (!isImm()) return false;
1076 const MCExpr
*E
= getImm();
1077 if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(E
)) {
1078 uint64_t Value
= CE
->getValue();
1080 return AArch64_AM::isMOVZMovAlias(Value
, Shift
, RegWidth
);
1082 // Only supports the case of Shift being 0 if an expression is used as an
1087 template<int RegWidth
, int Shift
>
1088 bool isMOVNMovAlias() const {
1089 if (!isImm()) return false;
1091 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
1092 if (!CE
) return false;
1093 uint64_t Value
= CE
->getValue();
1095 return AArch64_AM::isMOVNMovAlias(Value
, Shift
, RegWidth
);
1098 bool isFPImm() const {
1099 return Kind
== k_FPImm
&&
1100 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
1103 bool isBarrier() const {
1104 return Kind
== k_Barrier
&& !getBarriernXSModifier();
1106 bool isBarriernXS() const {
1107 return Kind
== k_Barrier
&& getBarriernXSModifier();
1109 bool isSysReg() const { return Kind
== k_SysReg
; }
1111 bool isMRSSystemRegister() const {
1112 if (!isSysReg()) return false;
1114 return SysReg
.MRSReg
!= -1U;
1117 bool isMSRSystemRegister() const {
1118 if (!isSysReg()) return false;
1119 return SysReg
.MSRReg
!= -1U;
1122 bool isSystemPStateFieldWithImm0_1() const {
1123 if (!isSysReg()) return false;
1124 return (SysReg
.PStateField
== AArch64PState::PAN
||
1125 SysReg
.PStateField
== AArch64PState::DIT
||
1126 SysReg
.PStateField
== AArch64PState::UAO
||
1127 SysReg
.PStateField
== AArch64PState::SSBS
);
1130 bool isSystemPStateFieldWithImm0_15() const {
1131 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
1132 return SysReg
.PStateField
!= -1U;
1135 bool isSVCR() const {
1138 return SVCR
.PStateField
!= -1U;
1141 bool isReg() const override
{
1142 return Kind
== k_Register
;
1145 bool isScalarReg() const {
1146 return Kind
== k_Register
&& Reg
.Kind
== RegKind::Scalar
;
1149 bool isNeonVectorReg() const {
1150 return Kind
== k_Register
&& Reg
.Kind
== RegKind::NeonVector
;
1153 bool isNeonVectorRegLo() const {
1154 return Kind
== k_Register
&& Reg
.Kind
== RegKind::NeonVector
&&
1155 (AArch64MCRegisterClasses
[AArch64::FPR128_loRegClassID
].contains(
1157 AArch64MCRegisterClasses
[AArch64::FPR64_loRegClassID
].contains(
1161 bool isMatrix() const { return Kind
== k_MatrixRegister
; }
1162 bool isMatrixTileList() const { return Kind
== k_MatrixTileList
; }
1164 template <unsigned Class
> bool isSVEVectorReg() const {
1167 case AArch64::ZPRRegClassID
:
1168 case AArch64::ZPR_3bRegClassID
:
1169 case AArch64::ZPR_4bRegClassID
:
1170 RK
= RegKind::SVEDataVector
;
1172 case AArch64::PPRRegClassID
:
1173 case AArch64::PPR_3bRegClassID
:
1174 RK
= RegKind::SVEPredicateVector
;
1177 llvm_unreachable("Unsupport register class");
1180 return (Kind
== k_Register
&& Reg
.Kind
== RK
) &&
1181 AArch64MCRegisterClasses
[Class
].contains(getReg());
1184 template <unsigned Class
> bool isFPRasZPR() const {
1185 return Kind
== k_Register
&& Reg
.Kind
== RegKind::Scalar
&&
1186 AArch64MCRegisterClasses
[Class
].contains(getReg());
1189 template <int ElementWidth
, unsigned Class
>
1190 DiagnosticPredicate
isSVEPredicateVectorRegOfWidth() const {
1191 if (Kind
!= k_Register
|| Reg
.Kind
!= RegKind::SVEPredicateVector
)
1192 return DiagnosticPredicateTy::NoMatch
;
1194 if (isSVEVectorReg
<Class
>() && (Reg
.ElementWidth
== ElementWidth
))
1195 return DiagnosticPredicateTy::Match
;
1197 return DiagnosticPredicateTy::NearMatch
;
1200 template <int ElementWidth
, unsigned Class
>
1201 DiagnosticPredicate
isSVEDataVectorRegOfWidth() const {
1202 if (Kind
!= k_Register
|| Reg
.Kind
!= RegKind::SVEDataVector
)
1203 return DiagnosticPredicateTy::NoMatch
;
1205 if (isSVEVectorReg
<Class
>() && Reg
.ElementWidth
== ElementWidth
)
1206 return DiagnosticPredicateTy::Match
;
1208 return DiagnosticPredicateTy::NearMatch
;
1211 template <int ElementWidth
, unsigned Class
,
1212 AArch64_AM::ShiftExtendType ShiftExtendTy
, int ShiftWidth
,
1213 bool ShiftWidthAlwaysSame
>
1214 DiagnosticPredicate
isSVEDataVectorRegWithShiftExtend() const {
1215 auto VectorMatch
= isSVEDataVectorRegOfWidth
<ElementWidth
, Class
>();
1216 if (!VectorMatch
.isMatch())
1217 return DiagnosticPredicateTy::NoMatch
;
1219 // Give a more specific diagnostic when the user has explicitly typed in
1220 // a shift-amount that does not match what is expected, but for which
1221 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1222 bool MatchShift
= getShiftExtendAmount() == Log2_32(ShiftWidth
/ 8);
1223 if (!MatchShift
&& (ShiftExtendTy
== AArch64_AM::UXTW
||
1224 ShiftExtendTy
== AArch64_AM::SXTW
) &&
1225 !ShiftWidthAlwaysSame
&& hasShiftExtendAmount() && ShiftWidth
== 8)
1226 return DiagnosticPredicateTy::NoMatch
;
1228 if (MatchShift
&& ShiftExtendTy
== getShiftExtendType())
1229 return DiagnosticPredicateTy::Match
;
1231 return DiagnosticPredicateTy::NearMatch
;
1234 bool isGPR32as64() const {
1235 return Kind
== k_Register
&& Reg
.Kind
== RegKind::Scalar
&&
1236 AArch64MCRegisterClasses
[AArch64::GPR64RegClassID
].contains(Reg
.RegNum
);
1239 bool isGPR64as32() const {
1240 return Kind
== k_Register
&& Reg
.Kind
== RegKind::Scalar
&&
1241 AArch64MCRegisterClasses
[AArch64::GPR32RegClassID
].contains(Reg
.RegNum
);
1244 bool isGPR64x8() const {
1245 return Kind
== k_Register
&& Reg
.Kind
== RegKind::Scalar
&&
1246 AArch64MCRegisterClasses
[AArch64::GPR64x8ClassRegClassID
].contains(
1250 bool isWSeqPair() const {
1251 return Kind
== k_Register
&& Reg
.Kind
== RegKind::Scalar
&&
1252 AArch64MCRegisterClasses
[AArch64::WSeqPairsClassRegClassID
].contains(
1256 bool isXSeqPair() const {
1257 return Kind
== k_Register
&& Reg
.Kind
== RegKind::Scalar
&&
1258 AArch64MCRegisterClasses
[AArch64::XSeqPairsClassRegClassID
].contains(
1262 template<int64_t Angle
, int64_t Remainder
>
1263 DiagnosticPredicate
isComplexRotation() const {
1264 if (!isImm()) return DiagnosticPredicateTy::NoMatch
;
1266 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
1267 if (!CE
) return DiagnosticPredicateTy::NoMatch
;
1268 uint64_t Value
= CE
->getValue();
1270 if (Value
% Angle
== Remainder
&& Value
<= 270)
1271 return DiagnosticPredicateTy::Match
;
1272 return DiagnosticPredicateTy::NearMatch
;
1275 template <unsigned RegClassID
> bool isGPR64() const {
1276 return Kind
== k_Register
&& Reg
.Kind
== RegKind::Scalar
&&
1277 AArch64MCRegisterClasses
[RegClassID
].contains(getReg());
1280 template <unsigned RegClassID
, int ExtWidth
>
1281 DiagnosticPredicate
isGPR64WithShiftExtend() const {
1282 if (Kind
!= k_Register
|| Reg
.Kind
!= RegKind::Scalar
)
1283 return DiagnosticPredicateTy::NoMatch
;
1285 if (isGPR64
<RegClassID
>() && getShiftExtendType() == AArch64_AM::LSL
&&
1286 getShiftExtendAmount() == Log2_32(ExtWidth
/ 8))
1287 return DiagnosticPredicateTy::Match
;
1288 return DiagnosticPredicateTy::NearMatch
;
1291 /// Is this a vector list with the type implicit (presumably attached to the
1292 /// instruction itself)?
1293 template <RegKind VectorKind
, unsigned NumRegs
>
1294 bool isImplicitlyTypedVectorList() const {
1295 return Kind
== k_VectorList
&& VectorList
.Count
== NumRegs
&&
1296 VectorList
.NumElements
== 0 &&
1297 VectorList
.RegisterKind
== VectorKind
;
1300 template <RegKind VectorKind
, unsigned NumRegs
, unsigned NumElements
,
1301 unsigned ElementWidth
>
1302 bool isTypedVectorList() const {
1303 if (Kind
!= k_VectorList
)
1305 if (VectorList
.Count
!= NumRegs
)
1307 if (VectorList
.RegisterKind
!= VectorKind
)
1309 if (VectorList
.ElementWidth
!= ElementWidth
)
1311 return VectorList
.NumElements
== NumElements
;
1314 template <int Min
, int Max
>
1315 DiagnosticPredicate
isVectorIndex() const {
1316 if (Kind
!= k_VectorIndex
)
1317 return DiagnosticPredicateTy::NoMatch
;
1318 if (VectorIndex
.Val
>= Min
&& VectorIndex
.Val
<= Max
)
1319 return DiagnosticPredicateTy::Match
;
1320 return DiagnosticPredicateTy::NearMatch
;
1323 bool isToken() const override
{ return Kind
== k_Token
; }
1325 bool isTokenEqual(StringRef Str
) const {
1326 return Kind
== k_Token
&& getToken() == Str
;
1328 bool isSysCR() const { return Kind
== k_SysCR
; }
1329 bool isPrefetch() const { return Kind
== k_Prefetch
; }
1330 bool isPSBHint() const { return Kind
== k_PSBHint
; }
1331 bool isBTIHint() const { return Kind
== k_BTIHint
; }
1332 bool isShiftExtend() const { return Kind
== k_ShiftExtend
; }
1333 bool isShifter() const {
1334 if (!isShiftExtend())
1337 AArch64_AM::ShiftExtendType ST
= getShiftExtendType();
1338 return (ST
== AArch64_AM::LSL
|| ST
== AArch64_AM::LSR
||
1339 ST
== AArch64_AM::ASR
|| ST
== AArch64_AM::ROR
||
1340 ST
== AArch64_AM::MSL
);
1343 template <unsigned ImmEnum
> DiagnosticPredicate
isExactFPImm() const {
1344 if (Kind
!= k_FPImm
)
1345 return DiagnosticPredicateTy::NoMatch
;
1347 if (getFPImmIsExact()) {
1348 // Lookup the immediate from table of supported immediates.
1349 auto *Desc
= AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum
);
1350 assert(Desc
&& "Unknown enum value");
1352 // Calculate its FP value.
1353 APFloat
RealVal(APFloat::IEEEdouble());
1355 RealVal
.convertFromString(Desc
->Repr
, APFloat::rmTowardZero
);
1356 if (errorToBool(StatusOrErr
.takeError()) || *StatusOrErr
!= APFloat::opOK
)
1357 llvm_unreachable("FP immediate is not exact");
1359 if (getFPImm().bitwiseIsEqual(RealVal
))
1360 return DiagnosticPredicateTy::Match
;
1363 return DiagnosticPredicateTy::NearMatch
;
1366 template <unsigned ImmA
, unsigned ImmB
>
1367 DiagnosticPredicate
isExactFPImm() const {
1368 DiagnosticPredicate Res
= DiagnosticPredicateTy::NoMatch
;
1369 if ((Res
= isExactFPImm
<ImmA
>()))
1370 return DiagnosticPredicateTy::Match
;
1371 if ((Res
= isExactFPImm
<ImmB
>()))
1372 return DiagnosticPredicateTy::Match
;
1376 bool isExtend() const {
1377 if (!isShiftExtend())
1380 AArch64_AM::ShiftExtendType ET
= getShiftExtendType();
1381 return (ET
== AArch64_AM::UXTB
|| ET
== AArch64_AM::SXTB
||
1382 ET
== AArch64_AM::UXTH
|| ET
== AArch64_AM::SXTH
||
1383 ET
== AArch64_AM::UXTW
|| ET
== AArch64_AM::SXTW
||
1384 ET
== AArch64_AM::UXTX
|| ET
== AArch64_AM::SXTX
||
1385 ET
== AArch64_AM::LSL
) &&
1386 getShiftExtendAmount() <= 4;
1389 bool isExtend64() const {
1392 // Make sure the extend expects a 32-bit source register.
1393 AArch64_AM::ShiftExtendType ET
= getShiftExtendType();
1394 return ET
== AArch64_AM::UXTB
|| ET
== AArch64_AM::SXTB
||
1395 ET
== AArch64_AM::UXTH
|| ET
== AArch64_AM::SXTH
||
1396 ET
== AArch64_AM::UXTW
|| ET
== AArch64_AM::SXTW
;
1399 bool isExtendLSL64() const {
1402 AArch64_AM::ShiftExtendType ET
= getShiftExtendType();
1403 return (ET
== AArch64_AM::UXTX
|| ET
== AArch64_AM::SXTX
||
1404 ET
== AArch64_AM::LSL
) &&
1405 getShiftExtendAmount() <= 4;
1408 template<int Width
> bool isMemXExtend() const {
1411 AArch64_AM::ShiftExtendType ET
= getShiftExtendType();
1412 return (ET
== AArch64_AM::LSL
|| ET
== AArch64_AM::SXTX
) &&
1413 (getShiftExtendAmount() == Log2_32(Width
/ 8) ||
1414 getShiftExtendAmount() == 0);
1417 template<int Width
> bool isMemWExtend() const {
1420 AArch64_AM::ShiftExtendType ET
= getShiftExtendType();
1421 return (ET
== AArch64_AM::UXTW
|| ET
== AArch64_AM::SXTW
) &&
1422 (getShiftExtendAmount() == Log2_32(Width
/ 8) ||
1423 getShiftExtendAmount() == 0);
1426 template <unsigned width
>
1427 bool isArithmeticShifter() const {
1431 // An arithmetic shifter is LSL, LSR, or ASR.
1432 AArch64_AM::ShiftExtendType ST
= getShiftExtendType();
1433 return (ST
== AArch64_AM::LSL
|| ST
== AArch64_AM::LSR
||
1434 ST
== AArch64_AM::ASR
) && getShiftExtendAmount() < width
;
1437 template <unsigned width
>
1438 bool isLogicalShifter() const {
1442 // A logical shifter is LSL, LSR, ASR or ROR.
1443 AArch64_AM::ShiftExtendType ST
= getShiftExtendType();
1444 return (ST
== AArch64_AM::LSL
|| ST
== AArch64_AM::LSR
||
1445 ST
== AArch64_AM::ASR
|| ST
== AArch64_AM::ROR
) &&
1446 getShiftExtendAmount() < width
;
1449 bool isMovImm32Shifter() const {
1453 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1454 AArch64_AM::ShiftExtendType ST
= getShiftExtendType();
1455 if (ST
!= AArch64_AM::LSL
)
1457 uint64_t Val
= getShiftExtendAmount();
1458 return (Val
== 0 || Val
== 16);
1461 bool isMovImm64Shifter() const {
1465 // A MOVi shifter is LSL of 0 or 16.
1466 AArch64_AM::ShiftExtendType ST
= getShiftExtendType();
1467 if (ST
!= AArch64_AM::LSL
)
1469 uint64_t Val
= getShiftExtendAmount();
1470 return (Val
== 0 || Val
== 16 || Val
== 32 || Val
== 48);
1473 bool isLogicalVecShifter() const {
1477 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1478 unsigned Shift
= getShiftExtendAmount();
1479 return getShiftExtendType() == AArch64_AM::LSL
&&
1480 (Shift
== 0 || Shift
== 8 || Shift
== 16 || Shift
== 24);
1483 bool isLogicalVecHalfWordShifter() const {
1484 if (!isLogicalVecShifter())
1487 // A logical vector shifter is a left shift by 0 or 8.
1488 unsigned Shift
= getShiftExtendAmount();
1489 return getShiftExtendType() == AArch64_AM::LSL
&&
1490 (Shift
== 0 || Shift
== 8);
1493 bool isMoveVecShifter() const {
1494 if (!isShiftExtend())
1497 // A logical vector shifter is a left shift by 8 or 16.
1498 unsigned Shift
= getShiftExtendAmount();
1499 return getShiftExtendType() == AArch64_AM::MSL
&&
1500 (Shift
== 8 || Shift
== 16);
1503 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1504 // to LDUR/STUR when the offset is not legal for the former but is for
1505 // the latter. As such, in addition to checking for being a legal unscaled
1506 // address, also check that it is not a legal scaled address. This avoids
1507 // ambiguity in the matcher.
1509 bool isSImm9OffsetFB() const {
1510 return isSImm
<9>() && !isUImm12Offset
<Width
/ 8>();
1513 bool isAdrpLabel() const {
1514 // Validation was handled during parsing, so we just sanity check that
1515 // something didn't go haywire.
1519 if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Imm
.Val
)) {
1520 int64_t Val
= CE
->getValue();
1521 int64_t Min
= - (4096 * (1LL << (21 - 1)));
1522 int64_t Max
= 4096 * ((1LL << (21 - 1)) - 1);
1523 return (Val
% 4096) == 0 && Val
>= Min
&& Val
<= Max
;
1529 bool isAdrLabel() const {
1530 // Validation was handled during parsing, so we just sanity check that
1531 // something didn't go haywire.
1535 if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Imm
.Val
)) {
1536 int64_t Val
= CE
->getValue();
1537 int64_t Min
= - (1LL << (21 - 1));
1538 int64_t Max
= ((1LL << (21 - 1)) - 1);
1539 return Val
>= Min
&& Val
<= Max
;
1545 template <MatrixKind Kind
, unsigned EltSize
, unsigned RegClass
>
1546 DiagnosticPredicate
isMatrixRegOperand() const {
1548 return DiagnosticPredicateTy::NoMatch
;
1549 if (getMatrixKind() != Kind
||
1550 !AArch64MCRegisterClasses
[RegClass
].contains(getMatrixReg()) ||
1551 EltSize
!= getMatrixElementWidth())
1552 return DiagnosticPredicateTy::NearMatch
;
1553 return DiagnosticPredicateTy::Match
;
1556 void addExpr(MCInst
&Inst
, const MCExpr
*Expr
) const {
1557 // Add as immediates when possible. Null MCExpr = 0.
1559 Inst
.addOperand(MCOperand::createImm(0));
1560 else if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Expr
))
1561 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
1563 Inst
.addOperand(MCOperand::createExpr(Expr
));
1566 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
1567 assert(N
== 1 && "Invalid number of operands!");
1568 Inst
.addOperand(MCOperand::createReg(getReg()));
1571 void addMatrixOperands(MCInst
&Inst
, unsigned N
) const {
1572 assert(N
== 1 && "Invalid number of operands!");
1573 Inst
.addOperand(MCOperand::createReg(getMatrixReg()));
1576 void addGPR32as64Operands(MCInst
&Inst
, unsigned N
) const {
1577 assert(N
== 1 && "Invalid number of operands!");
1579 AArch64MCRegisterClasses
[AArch64::GPR64RegClassID
].contains(getReg()));
1581 const MCRegisterInfo
*RI
= Ctx
.getRegisterInfo();
1582 uint32_t Reg
= RI
->getRegClass(AArch64::GPR32RegClassID
).getRegister(
1583 RI
->getEncodingValue(getReg()));
1585 Inst
.addOperand(MCOperand::createReg(Reg
));
1588 void addGPR64as32Operands(MCInst
&Inst
, unsigned N
) const {
1589 assert(N
== 1 && "Invalid number of operands!");
1591 AArch64MCRegisterClasses
[AArch64::GPR32RegClassID
].contains(getReg()));
1593 const MCRegisterInfo
*RI
= Ctx
.getRegisterInfo();
1594 uint32_t Reg
= RI
->getRegClass(AArch64::GPR64RegClassID
).getRegister(
1595 RI
->getEncodingValue(getReg()));
1597 Inst
.addOperand(MCOperand::createReg(Reg
));
1600 template <int Width
>
1601 void addFPRasZPRRegOperands(MCInst
&Inst
, unsigned N
) const {
1604 case 8: Base
= AArch64::B0
; break;
1605 case 16: Base
= AArch64::H0
; break;
1606 case 32: Base
= AArch64::S0
; break;
1607 case 64: Base
= AArch64::D0
; break;
1608 case 128: Base
= AArch64::Q0
; break;
1610 llvm_unreachable("Unsupported width");
1612 Inst
.addOperand(MCOperand::createReg(AArch64::Z0
+ getReg() - Base
));
1615 void addVectorReg64Operands(MCInst
&Inst
, unsigned N
) const {
1616 assert(N
== 1 && "Invalid number of operands!");
1618 AArch64MCRegisterClasses
[AArch64::FPR128RegClassID
].contains(getReg()));
1619 Inst
.addOperand(MCOperand::createReg(AArch64::D0
+ getReg() - AArch64::Q0
));
1622 void addVectorReg128Operands(MCInst
&Inst
, unsigned N
) const {
1623 assert(N
== 1 && "Invalid number of operands!");
1625 AArch64MCRegisterClasses
[AArch64::FPR128RegClassID
].contains(getReg()));
1626 Inst
.addOperand(MCOperand::createReg(getReg()));
1629 void addVectorRegLoOperands(MCInst
&Inst
, unsigned N
) const {
1630 assert(N
== 1 && "Invalid number of operands!");
1631 Inst
.addOperand(MCOperand::createReg(getReg()));
1634 enum VecListIndexType
{
1635 VecListIdx_DReg
= 0,
1636 VecListIdx_QReg
= 1,
1637 VecListIdx_ZReg
= 2,
1640 template <VecListIndexType RegTy
, unsigned NumRegs
>
1641 void addVectorListOperands(MCInst
&Inst
, unsigned N
) const {
1642 assert(N
== 1 && "Invalid number of operands!");
1643 static const unsigned FirstRegs
[][5] = {
1644 /* DReg */ { AArch64::Q0
,
1645 AArch64::D0
, AArch64::D0_D1
,
1646 AArch64::D0_D1_D2
, AArch64::D0_D1_D2_D3
},
1647 /* QReg */ { AArch64::Q0
,
1648 AArch64::Q0
, AArch64::Q0_Q1
,
1649 AArch64::Q0_Q1_Q2
, AArch64::Q0_Q1_Q2_Q3
},
1650 /* ZReg */ { AArch64::Z0
,
1651 AArch64::Z0
, AArch64::Z0_Z1
,
1652 AArch64::Z0_Z1_Z2
, AArch64::Z0_Z1_Z2_Z3
}
1655 assert((RegTy
!= VecListIdx_ZReg
|| NumRegs
<= 4) &&
1656 " NumRegs must be <= 4 for ZRegs");
1658 unsigned FirstReg
= FirstRegs
[(unsigned)RegTy
][NumRegs
];
1659 Inst
.addOperand(MCOperand::createReg(FirstReg
+ getVectorListStart() -
1660 FirstRegs
[(unsigned)RegTy
][0]));
1663 void addMatrixTileListOperands(MCInst
&Inst
, unsigned N
) const {
1664 assert(N
== 1 && "Invalid number of operands!");
1665 unsigned RegMask
= getMatrixTileListRegMask();
1666 assert(RegMask
<= 0xFF && "Invalid mask!");
1667 Inst
.addOperand(MCOperand::createImm(RegMask
));
1670 void addVectorIndexOperands(MCInst
&Inst
, unsigned N
) const {
1671 assert(N
== 1 && "Invalid number of operands!");
1672 Inst
.addOperand(MCOperand::createImm(getVectorIndex()));
1675 template <unsigned ImmIs0
, unsigned ImmIs1
>
1676 void addExactFPImmOperands(MCInst
&Inst
, unsigned N
) const {
1677 assert(N
== 1 && "Invalid number of operands!");
1678 assert(bool(isExactFPImm
<ImmIs0
, ImmIs1
>()) && "Invalid operand");
1679 Inst
.addOperand(MCOperand::createImm(bool(isExactFPImm
<ImmIs1
>())));
1682 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
1683 assert(N
== 1 && "Invalid number of operands!");
1684 // If this is a pageoff symrefexpr with an addend, adjust the addend
1685 // to be only the page-offset portion. Otherwise, just add the expr
1687 addExpr(Inst
, getImm());
1690 template <int Shift
>
1691 void addImmWithOptionalShiftOperands(MCInst
&Inst
, unsigned N
) const {
1692 assert(N
== 2 && "Invalid number of operands!");
1693 if (auto ShiftedVal
= getShiftedVal
<Shift
>()) {
1694 Inst
.addOperand(MCOperand::createImm(ShiftedVal
->first
));
1695 Inst
.addOperand(MCOperand::createImm(ShiftedVal
->second
));
1696 } else if (isShiftedImm()) {
1697 addExpr(Inst
, getShiftedImmVal());
1698 Inst
.addOperand(MCOperand::createImm(getShiftedImmShift()));
1700 addExpr(Inst
, getImm());
1701 Inst
.addOperand(MCOperand::createImm(0));
1705 template <int Shift
>
1706 void addImmNegWithOptionalShiftOperands(MCInst
&Inst
, unsigned N
) const {
1707 assert(N
== 2 && "Invalid number of operands!");
1708 if (auto ShiftedVal
= getShiftedVal
<Shift
>()) {
1709 Inst
.addOperand(MCOperand::createImm(-ShiftedVal
->first
));
1710 Inst
.addOperand(MCOperand::createImm(ShiftedVal
->second
));
1712 llvm_unreachable("Not a shifted negative immediate");
1715 void addCondCodeOperands(MCInst
&Inst
, unsigned N
) const {
1716 assert(N
== 1 && "Invalid number of operands!");
1717 Inst
.addOperand(MCOperand::createImm(getCondCode()));
1720 void addAdrpLabelOperands(MCInst
&Inst
, unsigned N
) const {
1721 assert(N
== 1 && "Invalid number of operands!");
1722 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
1724 addExpr(Inst
, getImm());
1726 Inst
.addOperand(MCOperand::createImm(MCE
->getValue() >> 12));
1729 void addAdrLabelOperands(MCInst
&Inst
, unsigned N
) const {
1730 addImmOperands(Inst
, N
);
1734 void addUImm12OffsetOperands(MCInst
&Inst
, unsigned N
) const {
1735 assert(N
== 1 && "Invalid number of operands!");
1736 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
1739 Inst
.addOperand(MCOperand::createExpr(getImm()));
1742 Inst
.addOperand(MCOperand::createImm(MCE
->getValue() / Scale
));
1745 void addUImm6Operands(MCInst
&Inst
, unsigned N
) const {
1746 assert(N
== 1 && "Invalid number of operands!");
1747 const MCConstantExpr
*MCE
= cast
<MCConstantExpr
>(getImm());
1748 Inst
.addOperand(MCOperand::createImm(MCE
->getValue()));
1751 template <int Scale
>
1752 void addImmScaledOperands(MCInst
&Inst
, unsigned N
) const {
1753 assert(N
== 1 && "Invalid number of operands!");
1754 const MCConstantExpr
*MCE
= cast
<MCConstantExpr
>(getImm());
1755 Inst
.addOperand(MCOperand::createImm(MCE
->getValue() / Scale
));
1758 template <typename T
>
1759 void addLogicalImmOperands(MCInst
&Inst
, unsigned N
) const {
1760 assert(N
== 1 && "Invalid number of operands!");
1761 const MCConstantExpr
*MCE
= cast
<MCConstantExpr
>(getImm());
1762 std::make_unsigned_t
<T
> Val
= MCE
->getValue();
1763 uint64_t encoding
= AArch64_AM::encodeLogicalImmediate(Val
, sizeof(T
) * 8);
1764 Inst
.addOperand(MCOperand::createImm(encoding
));
1767 template <typename T
>
1768 void addLogicalImmNotOperands(MCInst
&Inst
, unsigned N
) const {
1769 assert(N
== 1 && "Invalid number of operands!");
1770 const MCConstantExpr
*MCE
= cast
<MCConstantExpr
>(getImm());
1771 std::make_unsigned_t
<T
> Val
= ~MCE
->getValue();
1772 uint64_t encoding
= AArch64_AM::encodeLogicalImmediate(Val
, sizeof(T
) * 8);
1773 Inst
.addOperand(MCOperand::createImm(encoding
));
1776 void addSIMDImmType10Operands(MCInst
&Inst
, unsigned N
) const {
1777 assert(N
== 1 && "Invalid number of operands!");
1778 const MCConstantExpr
*MCE
= cast
<MCConstantExpr
>(getImm());
1779 uint64_t encoding
= AArch64_AM::encodeAdvSIMDModImmType10(MCE
->getValue());
1780 Inst
.addOperand(MCOperand::createImm(encoding
));
1783 void addBranchTarget26Operands(MCInst
&Inst
, unsigned N
) const {
1784 // Branch operands don't encode the low bits, so shift them off
1785 // here. If it's a label, however, just put it on directly as there's
1786 // not enough information now to do anything.
1787 assert(N
== 1 && "Invalid number of operands!");
1788 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
1790 addExpr(Inst
, getImm());
1793 assert(MCE
&& "Invalid constant immediate operand!");
1794 Inst
.addOperand(MCOperand::createImm(MCE
->getValue() >> 2));
1797 void addPCRelLabel19Operands(MCInst
&Inst
, unsigned N
) const {
1798 // Branch operands don't encode the low bits, so shift them off
1799 // here. If it's a label, however, just put it on directly as there's
1800 // not enough information now to do anything.
1801 assert(N
== 1 && "Invalid number of operands!");
1802 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
1804 addExpr(Inst
, getImm());
1807 assert(MCE
&& "Invalid constant immediate operand!");
1808 Inst
.addOperand(MCOperand::createImm(MCE
->getValue() >> 2));
1811 void addBranchTarget14Operands(MCInst
&Inst
, unsigned N
) const {
1812 // Branch operands don't encode the low bits, so shift them off
1813 // here. If it's a label, however, just put it on directly as there's
1814 // not enough information now to do anything.
1815 assert(N
== 1 && "Invalid number of operands!");
1816 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(getImm());
1818 addExpr(Inst
, getImm());
1821 assert(MCE
&& "Invalid constant immediate operand!");
1822 Inst
.addOperand(MCOperand::createImm(MCE
->getValue() >> 2));
1825 void addFPImmOperands(MCInst
&Inst
, unsigned N
) const {
1826 assert(N
== 1 && "Invalid number of operands!");
1827 Inst
.addOperand(MCOperand::createImm(
1828 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
1831 void addBarrierOperands(MCInst
&Inst
, unsigned N
) const {
1832 assert(N
== 1 && "Invalid number of operands!");
1833 Inst
.addOperand(MCOperand::createImm(getBarrier()));
1836 void addBarriernXSOperands(MCInst
&Inst
, unsigned N
) const {
1837 assert(N
== 1 && "Invalid number of operands!");
1838 Inst
.addOperand(MCOperand::createImm(getBarrier()));
1841 void addMRSSystemRegisterOperands(MCInst
&Inst
, unsigned N
) const {
1842 assert(N
== 1 && "Invalid number of operands!");
1844 Inst
.addOperand(MCOperand::createImm(SysReg
.MRSReg
));
1847 void addMSRSystemRegisterOperands(MCInst
&Inst
, unsigned N
) const {
1848 assert(N
== 1 && "Invalid number of operands!");
1850 Inst
.addOperand(MCOperand::createImm(SysReg
.MSRReg
));
1853 void addSystemPStateFieldWithImm0_1Operands(MCInst
&Inst
, unsigned N
) const {
1854 assert(N
== 1 && "Invalid number of operands!");
1856 Inst
.addOperand(MCOperand::createImm(SysReg
.PStateField
));
1859 void addSVCROperands(MCInst
&Inst
, unsigned N
) const {
1860 assert(N
== 1 && "Invalid number of operands!");
1862 Inst
.addOperand(MCOperand::createImm(SVCR
.PStateField
));
1865 void addSystemPStateFieldWithImm0_15Operands(MCInst
&Inst
, unsigned N
) const {
1866 assert(N
== 1 && "Invalid number of operands!");
1868 Inst
.addOperand(MCOperand::createImm(SysReg
.PStateField
));
1871 void addSysCROperands(MCInst
&Inst
, unsigned N
) const {
1872 assert(N
== 1 && "Invalid number of operands!");
1873 Inst
.addOperand(MCOperand::createImm(getSysCR()));
1876 void addPrefetchOperands(MCInst
&Inst
, unsigned N
) const {
1877 assert(N
== 1 && "Invalid number of operands!");
1878 Inst
.addOperand(MCOperand::createImm(getPrefetch()));
1881 void addPSBHintOperands(MCInst
&Inst
, unsigned N
) const {
1882 assert(N
== 1 && "Invalid number of operands!");
1883 Inst
.addOperand(MCOperand::createImm(getPSBHint()));
1886 void addBTIHintOperands(MCInst
&Inst
, unsigned N
) const {
1887 assert(N
== 1 && "Invalid number of operands!");
1888 Inst
.addOperand(MCOperand::createImm(getBTIHint()));
1891 void addShifterOperands(MCInst
&Inst
, unsigned N
) const {
1892 assert(N
== 1 && "Invalid number of operands!");
1894 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
1895 Inst
.addOperand(MCOperand::createImm(Imm
));
1898 void addExtendOperands(MCInst
&Inst
, unsigned N
) const {
1899 assert(N
== 1 && "Invalid number of operands!");
1900 AArch64_AM::ShiftExtendType ET
= getShiftExtendType();
1901 if (ET
== AArch64_AM::LSL
) ET
= AArch64_AM::UXTW
;
1902 unsigned Imm
= AArch64_AM::getArithExtendImm(ET
, getShiftExtendAmount());
1903 Inst
.addOperand(MCOperand::createImm(Imm
));
1906 void addExtend64Operands(MCInst
&Inst
, unsigned N
) const {
1907 assert(N
== 1 && "Invalid number of operands!");
1908 AArch64_AM::ShiftExtendType ET
= getShiftExtendType();
1909 if (ET
== AArch64_AM::LSL
) ET
= AArch64_AM::UXTX
;
1910 unsigned Imm
= AArch64_AM::getArithExtendImm(ET
, getShiftExtendAmount());
1911 Inst
.addOperand(MCOperand::createImm(Imm
));
1914 void addMemExtendOperands(MCInst
&Inst
, unsigned N
) const {
1915 assert(N
== 2 && "Invalid number of operands!");
1916 AArch64_AM::ShiftExtendType ET
= getShiftExtendType();
1917 bool IsSigned
= ET
== AArch64_AM::SXTW
|| ET
== AArch64_AM::SXTX
;
1918 Inst
.addOperand(MCOperand::createImm(IsSigned
));
1919 Inst
.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
1922 // For 8-bit load/store instructions with a register offset, both the
1923 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1924 // they're disambiguated by whether the shift was explicit or implicit rather
1926 void addMemExtend8Operands(MCInst
&Inst
, unsigned N
) const {
1927 assert(N
== 2 && "Invalid number of operands!");
1928 AArch64_AM::ShiftExtendType ET
= getShiftExtendType();
1929 bool IsSigned
= ET
== AArch64_AM::SXTW
|| ET
== AArch64_AM::SXTX
;
1930 Inst
.addOperand(MCOperand::createImm(IsSigned
));
1931 Inst
.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
1935 void addMOVZMovAliasOperands(MCInst
&Inst
, unsigned N
) const {
1936 assert(N
== 1 && "Invalid number of operands!");
1938 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
1940 uint64_t Value
= CE
->getValue();
1941 Inst
.addOperand(MCOperand::createImm((Value
>> Shift
) & 0xffff));
1943 addExpr(Inst
, getImm());
1948 void addMOVNMovAliasOperands(MCInst
&Inst
, unsigned N
) const {
1949 assert(N
== 1 && "Invalid number of operands!");
1951 const MCConstantExpr
*CE
= cast
<MCConstantExpr
>(getImm());
1952 uint64_t Value
= CE
->getValue();
1953 Inst
.addOperand(MCOperand::createImm((~Value
>> Shift
) & 0xffff));
1956 void addComplexRotationEvenOperands(MCInst
&Inst
, unsigned N
) const {
1957 assert(N
== 1 && "Invalid number of operands!");
1958 const MCConstantExpr
*MCE
= cast
<MCConstantExpr
>(getImm());
1959 Inst
.addOperand(MCOperand::createImm(MCE
->getValue() / 90));
1962 void addComplexRotationOddOperands(MCInst
&Inst
, unsigned N
) const {
1963 assert(N
== 1 && "Invalid number of operands!");
1964 const MCConstantExpr
*MCE
= cast
<MCConstantExpr
>(getImm());
1965 Inst
.addOperand(MCOperand::createImm((MCE
->getValue() - 90) / 180));
1968 void print(raw_ostream
&OS
) const override
;
1970 static std::unique_ptr
<AArch64Operand
>
1971 CreateToken(StringRef Str
, SMLoc S
, MCContext
&Ctx
, bool IsSuffix
= false) {
1972 auto Op
= std::make_unique
<AArch64Operand
>(k_Token
, Ctx
);
1973 Op
->Tok
.Data
= Str
.data();
1974 Op
->Tok
.Length
= Str
.size();
1975 Op
->Tok
.IsSuffix
= IsSuffix
;
1981 static std::unique_ptr
<AArch64Operand
>
1982 CreateReg(unsigned RegNum
, RegKind Kind
, SMLoc S
, SMLoc E
, MCContext
&Ctx
,
1983 RegConstraintEqualityTy EqTy
= RegConstraintEqualityTy::EqualsReg
,
1984 AArch64_AM::ShiftExtendType ExtTy
= AArch64_AM::LSL
,
1985 unsigned ShiftAmount
= 0,
1986 unsigned HasExplicitAmount
= false) {
1987 auto Op
= std::make_unique
<AArch64Operand
>(k_Register
, Ctx
);
1988 Op
->Reg
.RegNum
= RegNum
;
1989 Op
->Reg
.Kind
= Kind
;
1990 Op
->Reg
.ElementWidth
= 0;
1991 Op
->Reg
.EqualityTy
= EqTy
;
1992 Op
->Reg
.ShiftExtend
.Type
= ExtTy
;
1993 Op
->Reg
.ShiftExtend
.Amount
= ShiftAmount
;
1994 Op
->Reg
.ShiftExtend
.HasExplicitAmount
= HasExplicitAmount
;
2000 static std::unique_ptr
<AArch64Operand
>
2001 CreateVectorReg(unsigned RegNum
, RegKind Kind
, unsigned ElementWidth
,
2002 SMLoc S
, SMLoc E
, MCContext
&Ctx
,
2003 AArch64_AM::ShiftExtendType ExtTy
= AArch64_AM::LSL
,
2004 unsigned ShiftAmount
= 0,
2005 unsigned HasExplicitAmount
= false) {
2006 assert((Kind
== RegKind::NeonVector
|| Kind
== RegKind::SVEDataVector
||
2007 Kind
== RegKind::SVEPredicateVector
) &&
2008 "Invalid vector kind");
2009 auto Op
= CreateReg(RegNum
, Kind
, S
, E
, Ctx
, EqualsReg
, ExtTy
, ShiftAmount
,
2011 Op
->Reg
.ElementWidth
= ElementWidth
;
2015 static std::unique_ptr
<AArch64Operand
>
2016 CreateVectorList(unsigned RegNum
, unsigned Count
, unsigned NumElements
,
2017 unsigned ElementWidth
, RegKind RegisterKind
, SMLoc S
, SMLoc E
,
2019 auto Op
= std::make_unique
<AArch64Operand
>(k_VectorList
, Ctx
);
2020 Op
->VectorList
.RegNum
= RegNum
;
2021 Op
->VectorList
.Count
= Count
;
2022 Op
->VectorList
.NumElements
= NumElements
;
2023 Op
->VectorList
.ElementWidth
= ElementWidth
;
2024 Op
->VectorList
.RegisterKind
= RegisterKind
;
2030 static std::unique_ptr
<AArch64Operand
>
2031 CreateVectorIndex(int Idx
, SMLoc S
, SMLoc E
, MCContext
&Ctx
) {
2032 auto Op
= std::make_unique
<AArch64Operand
>(k_VectorIndex
, Ctx
);
2033 Op
->VectorIndex
.Val
= Idx
;
2039 static std::unique_ptr
<AArch64Operand
>
2040 CreateMatrixTileList(unsigned RegMask
, SMLoc S
, SMLoc E
, MCContext
&Ctx
) {
2041 auto Op
= std::make_unique
<AArch64Operand
>(k_MatrixTileList
, Ctx
);
2042 Op
->MatrixTileList
.RegMask
= RegMask
;
2048 static void ComputeRegsForAlias(unsigned Reg
, SmallSet
<unsigned, 8> &OutRegs
,
2049 const unsigned ElementWidth
) {
2050 static std::map
<std::pair
<unsigned, unsigned>, std::vector
<unsigned>>
2052 {{0, AArch64::ZAB0
},
2053 {AArch64::ZAD0
, AArch64::ZAD1
, AArch64::ZAD2
, AArch64::ZAD3
,
2054 AArch64::ZAD4
, AArch64::ZAD5
, AArch64::ZAD6
, AArch64::ZAD7
}},
2055 {{8, AArch64::ZAB0
},
2056 {AArch64::ZAD0
, AArch64::ZAD1
, AArch64::ZAD2
, AArch64::ZAD3
,
2057 AArch64::ZAD4
, AArch64::ZAD5
, AArch64::ZAD6
, AArch64::ZAD7
}},
2058 {{16, AArch64::ZAH0
},
2059 {AArch64::ZAD0
, AArch64::ZAD2
, AArch64::ZAD4
, AArch64::ZAD6
}},
2060 {{16, AArch64::ZAH1
},
2061 {AArch64::ZAD1
, AArch64::ZAD3
, AArch64::ZAD5
, AArch64::ZAD7
}},
2062 {{32, AArch64::ZAS0
}, {AArch64::ZAD0
, AArch64::ZAD4
}},
2063 {{32, AArch64::ZAS1
}, {AArch64::ZAD1
, AArch64::ZAD5
}},
2064 {{32, AArch64::ZAS2
}, {AArch64::ZAD2
, AArch64::ZAD6
}},
2065 {{32, AArch64::ZAS3
}, {AArch64::ZAD3
, AArch64::ZAD7
}},
2068 if (ElementWidth
== 64)
2069 OutRegs
.insert(Reg
);
2071 std::vector
<unsigned> Regs
= RegMap
[std::make_pair(ElementWidth
, Reg
)];
2072 assert(!Regs
.empty() && "Invalid tile or element width!");
2073 for (auto OutReg
: Regs
)
2074 OutRegs
.insert(OutReg
);
2078 static std::unique_ptr
<AArch64Operand
> CreateImm(const MCExpr
*Val
, SMLoc S
,
2079 SMLoc E
, MCContext
&Ctx
) {
2080 auto Op
= std::make_unique
<AArch64Operand
>(k_Immediate
, Ctx
);
2087 static std::unique_ptr
<AArch64Operand
> CreateShiftedImm(const MCExpr
*Val
,
2088 unsigned ShiftAmount
,
2091 auto Op
= std::make_unique
<AArch64Operand
>(k_ShiftedImm
, Ctx
);
2092 Op
->ShiftedImm
.Val
= Val
;
2093 Op
->ShiftedImm
.ShiftAmount
= ShiftAmount
;
2099 static std::unique_ptr
<AArch64Operand
>
2100 CreateCondCode(AArch64CC::CondCode Code
, SMLoc S
, SMLoc E
, MCContext
&Ctx
) {
2101 auto Op
= std::make_unique
<AArch64Operand
>(k_CondCode
, Ctx
);
2102 Op
->CondCode
.Code
= Code
;
2108 static std::unique_ptr
<AArch64Operand
>
2109 CreateFPImm(APFloat Val
, bool IsExact
, SMLoc S
, MCContext
&Ctx
) {
2110 auto Op
= std::make_unique
<AArch64Operand
>(k_FPImm
, Ctx
);
2111 Op
->FPImm
.Val
= Val
.bitcastToAPInt().getSExtValue();
2112 Op
->FPImm
.IsExact
= IsExact
;
2118 static std::unique_ptr
<AArch64Operand
> CreateBarrier(unsigned Val
,
2122 bool HasnXSModifier
) {
2123 auto Op
= std::make_unique
<AArch64Operand
>(k_Barrier
, Ctx
);
2124 Op
->Barrier
.Val
= Val
;
2125 Op
->Barrier
.Data
= Str
.data();
2126 Op
->Barrier
.Length
= Str
.size();
2127 Op
->Barrier
.HasnXSModifier
= HasnXSModifier
;
2133 static std::unique_ptr
<AArch64Operand
> CreateSysReg(StringRef Str
, SMLoc S
,
2136 uint32_t PStateField
,
2138 auto Op
= std::make_unique
<AArch64Operand
>(k_SysReg
, Ctx
);
2139 Op
->SysReg
.Data
= Str
.data();
2140 Op
->SysReg
.Length
= Str
.size();
2141 Op
->SysReg
.MRSReg
= MRSReg
;
2142 Op
->SysReg
.MSRReg
= MSRReg
;
2143 Op
->SysReg
.PStateField
= PStateField
;
2149 static std::unique_ptr
<AArch64Operand
> CreateSysCR(unsigned Val
, SMLoc S
,
2150 SMLoc E
, MCContext
&Ctx
) {
2151 auto Op
= std::make_unique
<AArch64Operand
>(k_SysCR
, Ctx
);
2152 Op
->SysCRImm
.Val
= Val
;
2158 static std::unique_ptr
<AArch64Operand
> CreatePrefetch(unsigned Val
,
2162 auto Op
= std::make_unique
<AArch64Operand
>(k_Prefetch
, Ctx
);
2163 Op
->Prefetch
.Val
= Val
;
2164 Op
->Barrier
.Data
= Str
.data();
2165 Op
->Barrier
.Length
= Str
.size();
2171 static std::unique_ptr
<AArch64Operand
> CreatePSBHint(unsigned Val
,
2175 auto Op
= std::make_unique
<AArch64Operand
>(k_PSBHint
, Ctx
);
2176 Op
->PSBHint
.Val
= Val
;
2177 Op
->PSBHint
.Data
= Str
.data();
2178 Op
->PSBHint
.Length
= Str
.size();
2184 static std::unique_ptr
<AArch64Operand
> CreateBTIHint(unsigned Val
,
2188 auto Op
= std::make_unique
<AArch64Operand
>(k_BTIHint
, Ctx
);
2189 Op
->BTIHint
.Val
= Val
| 32;
2190 Op
->BTIHint
.Data
= Str
.data();
2191 Op
->BTIHint
.Length
= Str
.size();
2197 static std::unique_ptr
<AArch64Operand
>
2198 CreateMatrixRegister(unsigned RegNum
, unsigned ElementWidth
, MatrixKind Kind
,
2199 SMLoc S
, SMLoc E
, MCContext
&Ctx
) {
2200 auto Op
= std::make_unique
<AArch64Operand
>(k_MatrixRegister
, Ctx
);
2201 Op
->MatrixReg
.RegNum
= RegNum
;
2202 Op
->MatrixReg
.ElementWidth
= ElementWidth
;
2203 Op
->MatrixReg
.Kind
= Kind
;
2209 static std::unique_ptr
<AArch64Operand
>
2210 CreateSVCR(uint32_t PStateField
, StringRef Str
, SMLoc S
, MCContext
&Ctx
) {
2211 auto Op
= std::make_unique
<AArch64Operand
>(k_SVCR
, Ctx
);
2212 Op
->SVCR
.PStateField
= PStateField
;
2213 Op
->SVCR
.Data
= Str
.data();
2214 Op
->SVCR
.Length
= Str
.size();
2220 static std::unique_ptr
<AArch64Operand
>
2221 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp
, unsigned Val
,
2222 bool HasExplicitAmount
, SMLoc S
, SMLoc E
, MCContext
&Ctx
) {
2223 auto Op
= std::make_unique
<AArch64Operand
>(k_ShiftExtend
, Ctx
);
2224 Op
->ShiftExtend
.Type
= ShOp
;
2225 Op
->ShiftExtend
.Amount
= Val
;
2226 Op
->ShiftExtend
.HasExplicitAmount
= HasExplicitAmount
;
2233 } // end anonymous namespace.
2235 void AArch64Operand::print(raw_ostream
&OS
) const {
2238 OS
<< "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2239 if (!getFPImmIsExact())
2244 StringRef Name
= getBarrierName();
2246 OS
<< "<barrier " << Name
<< ">";
2248 OS
<< "<barrier invalid #" << getBarrier() << ">";
2254 case k_ShiftedImm
: {
2255 unsigned Shift
= getShiftedImmShift();
2256 OS
<< "<shiftedimm ";
2257 OS
<< *getShiftedImmVal();
2258 OS
<< ", lsl #" << AArch64_AM::getShiftValue(Shift
) << ">";
2262 OS
<< "<condcode " << getCondCode() << ">";
2264 case k_VectorList
: {
2265 OS
<< "<vectorlist ";
2266 unsigned Reg
= getVectorListStart();
2267 for (unsigned i
= 0, e
= getVectorListCount(); i
!= e
; ++i
)
2268 OS
<< Reg
+ i
<< " ";
2273 OS
<< "<vectorindex " << getVectorIndex() << ">";
2276 OS
<< "<sysreg: " << getSysReg() << '>';
2279 OS
<< "'" << getToken() << "'";
2282 OS
<< "c" << getSysCR();
2285 StringRef Name
= getPrefetchName();
2287 OS
<< "<prfop " << Name
<< ">";
2289 OS
<< "<prfop invalid #" << getPrefetch() << ">";
2293 OS
<< getPSBHintName();
2296 OS
<< getBTIHintName();
2298 case k_MatrixRegister
:
2299 OS
<< "<matrix " << getMatrixReg() << ">";
2301 case k_MatrixTileList
: {
2302 OS
<< "<matrixlist ";
2303 unsigned RegMask
= getMatrixTileListRegMask();
2304 unsigned MaxBits
= 8;
2305 for (unsigned I
= MaxBits
; I
> 0; --I
)
2306 OS
<< ((RegMask
& (1 << (I
- 1))) >> (I
- 1));
2315 OS
<< "<register " << getReg() << ">";
2316 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2320 OS
<< "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2321 << getShiftExtendAmount();
2322 if (!hasShiftExtendAmount())
2329 /// @name Auto-generated Match Functions
2332 static unsigned MatchRegisterName(StringRef Name
);
2336 static unsigned MatchNeonVectorRegName(StringRef Name
) {
2337 return StringSwitch
<unsigned>(Name
.lower())
2338 .Case("v0", AArch64::Q0
)
2339 .Case("v1", AArch64::Q1
)
2340 .Case("v2", AArch64::Q2
)
2341 .Case("v3", AArch64::Q3
)
2342 .Case("v4", AArch64::Q4
)
2343 .Case("v5", AArch64::Q5
)
2344 .Case("v6", AArch64::Q6
)
2345 .Case("v7", AArch64::Q7
)
2346 .Case("v8", AArch64::Q8
)
2347 .Case("v9", AArch64::Q9
)
2348 .Case("v10", AArch64::Q10
)
2349 .Case("v11", AArch64::Q11
)
2350 .Case("v12", AArch64::Q12
)
2351 .Case("v13", AArch64::Q13
)
2352 .Case("v14", AArch64::Q14
)
2353 .Case("v15", AArch64::Q15
)
2354 .Case("v16", AArch64::Q16
)
2355 .Case("v17", AArch64::Q17
)
2356 .Case("v18", AArch64::Q18
)
2357 .Case("v19", AArch64::Q19
)
2358 .Case("v20", AArch64::Q20
)
2359 .Case("v21", AArch64::Q21
)
2360 .Case("v22", AArch64::Q22
)
2361 .Case("v23", AArch64::Q23
)
2362 .Case("v24", AArch64::Q24
)
2363 .Case("v25", AArch64::Q25
)
2364 .Case("v26", AArch64::Q26
)
2365 .Case("v27", AArch64::Q27
)
2366 .Case("v28", AArch64::Q28
)
2367 .Case("v29", AArch64::Q29
)
2368 .Case("v30", AArch64::Q30
)
2369 .Case("v31", AArch64::Q31
)
2373 /// Returns an optional pair of (#elements, element-width) if Suffix
2374 /// is a valid vector kind. Where the number of elements in a vector
2375 /// or the vector width is implicit or explicitly unknown (but still a
2376 /// valid suffix kind), 0 is used.
2377 static Optional
<std::pair
<int, int>> parseVectorKind(StringRef Suffix
,
2378 RegKind VectorKind
) {
2379 std::pair
<int, int> Res
= {-1, -1};
2381 switch (VectorKind
) {
2382 case RegKind::NeonVector
:
2384 StringSwitch
<std::pair
<int, int>>(Suffix
.lower())
2386 .Case(".1d", {1, 64})
2387 .Case(".1q", {1, 128})
2388 // '.2h' needed for fp16 scalar pairwise reductions
2389 .Case(".2h", {2, 16})
2390 .Case(".2s", {2, 32})
2391 .Case(".2d", {2, 64})
2392 // '.4b' is another special case for the ARMv8.2a dot product
2394 .Case(".4b", {4, 8})
2395 .Case(".4h", {4, 16})
2396 .Case(".4s", {4, 32})
2397 .Case(".8b", {8, 8})
2398 .Case(".8h", {8, 16})
2399 .Case(".16b", {16, 8})
2400 // Accept the width neutral ones, too, for verbose syntax. If those
2401 // aren't used in the right places, the token operand won't match so
2402 // all will work out.
2404 .Case(".h", {0, 16})
2405 .Case(".s", {0, 32})
2406 .Case(".d", {0, 64})
2409 case RegKind::SVEPredicateVector
:
2410 case RegKind::SVEDataVector
:
2411 case RegKind::Matrix
:
2412 Res
= StringSwitch
<std::pair
<int, int>>(Suffix
.lower())
2415 .Case(".h", {0, 16})
2416 .Case(".s", {0, 32})
2417 .Case(".d", {0, 64})
2418 .Case(".q", {0, 128})
2422 llvm_unreachable("Unsupported RegKind");
2425 if (Res
== std::make_pair(-1, -1))
2426 return Optional
<std::pair
<int, int>>();
2428 return Optional
<std::pair
<int, int>>(Res
);
2431 static bool isValidVectorKind(StringRef Suffix
, RegKind VectorKind
) {
2432 return parseVectorKind(Suffix
, VectorKind
).hasValue();
2435 static unsigned matchSVEDataVectorRegName(StringRef Name
) {
2436 return StringSwitch
<unsigned>(Name
.lower())
2437 .Case("z0", AArch64::Z0
)
2438 .Case("z1", AArch64::Z1
)
2439 .Case("z2", AArch64::Z2
)
2440 .Case("z3", AArch64::Z3
)
2441 .Case("z4", AArch64::Z4
)
2442 .Case("z5", AArch64::Z5
)
2443 .Case("z6", AArch64::Z6
)
2444 .Case("z7", AArch64::Z7
)
2445 .Case("z8", AArch64::Z8
)
2446 .Case("z9", AArch64::Z9
)
2447 .Case("z10", AArch64::Z10
)
2448 .Case("z11", AArch64::Z11
)
2449 .Case("z12", AArch64::Z12
)
2450 .Case("z13", AArch64::Z13
)
2451 .Case("z14", AArch64::Z14
)
2452 .Case("z15", AArch64::Z15
)
2453 .Case("z16", AArch64::Z16
)
2454 .Case("z17", AArch64::Z17
)
2455 .Case("z18", AArch64::Z18
)
2456 .Case("z19", AArch64::Z19
)
2457 .Case("z20", AArch64::Z20
)
2458 .Case("z21", AArch64::Z21
)
2459 .Case("z22", AArch64::Z22
)
2460 .Case("z23", AArch64::Z23
)
2461 .Case("z24", AArch64::Z24
)
2462 .Case("z25", AArch64::Z25
)
2463 .Case("z26", AArch64::Z26
)
2464 .Case("z27", AArch64::Z27
)
2465 .Case("z28", AArch64::Z28
)
2466 .Case("z29", AArch64::Z29
)
2467 .Case("z30", AArch64::Z30
)
2468 .Case("z31", AArch64::Z31
)
2472 static unsigned matchSVEPredicateVectorRegName(StringRef Name
) {
2473 return StringSwitch
<unsigned>(Name
.lower())
2474 .Case("p0", AArch64::P0
)
2475 .Case("p1", AArch64::P1
)
2476 .Case("p2", AArch64::P2
)
2477 .Case("p3", AArch64::P3
)
2478 .Case("p4", AArch64::P4
)
2479 .Case("p5", AArch64::P5
)
2480 .Case("p6", AArch64::P6
)
2481 .Case("p7", AArch64::P7
)
2482 .Case("p8", AArch64::P8
)
2483 .Case("p9", AArch64::P9
)
2484 .Case("p10", AArch64::P10
)
2485 .Case("p11", AArch64::P11
)
2486 .Case("p12", AArch64::P12
)
2487 .Case("p13", AArch64::P13
)
2488 .Case("p14", AArch64::P14
)
2489 .Case("p15", AArch64::P15
)
2493 static unsigned matchMatrixTileListRegName(StringRef Name
) {
2494 return StringSwitch
<unsigned>(Name
.lower())
2495 .Case("za0.d", AArch64::ZAD0
)
2496 .Case("za1.d", AArch64::ZAD1
)
2497 .Case("za2.d", AArch64::ZAD2
)
2498 .Case("za3.d", AArch64::ZAD3
)
2499 .Case("za4.d", AArch64::ZAD4
)
2500 .Case("za5.d", AArch64::ZAD5
)
2501 .Case("za6.d", AArch64::ZAD6
)
2502 .Case("za7.d", AArch64::ZAD7
)
2503 .Case("za0.s", AArch64::ZAS0
)
2504 .Case("za1.s", AArch64::ZAS1
)
2505 .Case("za2.s", AArch64::ZAS2
)
2506 .Case("za3.s", AArch64::ZAS3
)
2507 .Case("za0.h", AArch64::ZAH0
)
2508 .Case("za1.h", AArch64::ZAH1
)
2509 .Case("za0.b", AArch64::ZAB0
)
2513 static unsigned matchMatrixRegName(StringRef Name
) {
2514 return StringSwitch
<unsigned>(Name
.lower())
2515 .Case("za", AArch64::ZA
)
2516 .Case("za0.q", AArch64::ZAQ0
)
2517 .Case("za1.q", AArch64::ZAQ1
)
2518 .Case("za2.q", AArch64::ZAQ2
)
2519 .Case("za3.q", AArch64::ZAQ3
)
2520 .Case("za4.q", AArch64::ZAQ4
)
2521 .Case("za5.q", AArch64::ZAQ5
)
2522 .Case("za6.q", AArch64::ZAQ6
)
2523 .Case("za7.q", AArch64::ZAQ7
)
2524 .Case("za8.q", AArch64::ZAQ8
)
2525 .Case("za9.q", AArch64::ZAQ9
)
2526 .Case("za10.q", AArch64::ZAQ10
)
2527 .Case("za11.q", AArch64::ZAQ11
)
2528 .Case("za12.q", AArch64::ZAQ12
)
2529 .Case("za13.q", AArch64::ZAQ13
)
2530 .Case("za14.q", AArch64::ZAQ14
)
2531 .Case("za15.q", AArch64::ZAQ15
)
2532 .Case("za0.d", AArch64::ZAD0
)
2533 .Case("za1.d", AArch64::ZAD1
)
2534 .Case("za2.d", AArch64::ZAD2
)
2535 .Case("za3.d", AArch64::ZAD3
)
2536 .Case("za4.d", AArch64::ZAD4
)
2537 .Case("za5.d", AArch64::ZAD5
)
2538 .Case("za6.d", AArch64::ZAD6
)
2539 .Case("za7.d", AArch64::ZAD7
)
2540 .Case("za0.s", AArch64::ZAS0
)
2541 .Case("za1.s", AArch64::ZAS1
)
2542 .Case("za2.s", AArch64::ZAS2
)
2543 .Case("za3.s", AArch64::ZAS3
)
2544 .Case("za0.h", AArch64::ZAH0
)
2545 .Case("za1.h", AArch64::ZAH1
)
2546 .Case("za0.b", AArch64::ZAB0
)
2547 .Case("za0h.q", AArch64::ZAQ0
)
2548 .Case("za1h.q", AArch64::ZAQ1
)
2549 .Case("za2h.q", AArch64::ZAQ2
)
2550 .Case("za3h.q", AArch64::ZAQ3
)
2551 .Case("za4h.q", AArch64::ZAQ4
)
2552 .Case("za5h.q", AArch64::ZAQ5
)
2553 .Case("za6h.q", AArch64::ZAQ6
)
2554 .Case("za7h.q", AArch64::ZAQ7
)
2555 .Case("za8h.q", AArch64::ZAQ8
)
2556 .Case("za9h.q", AArch64::ZAQ9
)
2557 .Case("za10h.q", AArch64::ZAQ10
)
2558 .Case("za11h.q", AArch64::ZAQ11
)
2559 .Case("za12h.q", AArch64::ZAQ12
)
2560 .Case("za13h.q", AArch64::ZAQ13
)
2561 .Case("za14h.q", AArch64::ZAQ14
)
2562 .Case("za15h.q", AArch64::ZAQ15
)
2563 .Case("za0h.d", AArch64::ZAD0
)
2564 .Case("za1h.d", AArch64::ZAD1
)
2565 .Case("za2h.d", AArch64::ZAD2
)
2566 .Case("za3h.d", AArch64::ZAD3
)
2567 .Case("za4h.d", AArch64::ZAD4
)
2568 .Case("za5h.d", AArch64::ZAD5
)
2569 .Case("za6h.d", AArch64::ZAD6
)
2570 .Case("za7h.d", AArch64::ZAD7
)
2571 .Case("za0h.s", AArch64::ZAS0
)
2572 .Case("za1h.s", AArch64::ZAS1
)
2573 .Case("za2h.s", AArch64::ZAS2
)
2574 .Case("za3h.s", AArch64::ZAS3
)
2575 .Case("za0h.h", AArch64::ZAH0
)
2576 .Case("za1h.h", AArch64::ZAH1
)
2577 .Case("za0h.b", AArch64::ZAB0
)
2578 .Case("za0v.q", AArch64::ZAQ0
)
2579 .Case("za1v.q", AArch64::ZAQ1
)
2580 .Case("za2v.q", AArch64::ZAQ2
)
2581 .Case("za3v.q", AArch64::ZAQ3
)
2582 .Case("za4v.q", AArch64::ZAQ4
)
2583 .Case("za5v.q", AArch64::ZAQ5
)
2584 .Case("za6v.q", AArch64::ZAQ6
)
2585 .Case("za7v.q", AArch64::ZAQ7
)
2586 .Case("za8v.q", AArch64::ZAQ8
)
2587 .Case("za9v.q", AArch64::ZAQ9
)
2588 .Case("za10v.q", AArch64::ZAQ10
)
2589 .Case("za11v.q", AArch64::ZAQ11
)
2590 .Case("za12v.q", AArch64::ZAQ12
)
2591 .Case("za13v.q", AArch64::ZAQ13
)
2592 .Case("za14v.q", AArch64::ZAQ14
)
2593 .Case("za15v.q", AArch64::ZAQ15
)
2594 .Case("za0v.d", AArch64::ZAD0
)
2595 .Case("za1v.d", AArch64::ZAD1
)
2596 .Case("za2v.d", AArch64::ZAD2
)
2597 .Case("za3v.d", AArch64::ZAD3
)
2598 .Case("za4v.d", AArch64::ZAD4
)
2599 .Case("za5v.d", AArch64::ZAD5
)
2600 .Case("za6v.d", AArch64::ZAD6
)
2601 .Case("za7v.d", AArch64::ZAD7
)
2602 .Case("za0v.s", AArch64::ZAS0
)
2603 .Case("za1v.s", AArch64::ZAS1
)
2604 .Case("za2v.s", AArch64::ZAS2
)
2605 .Case("za3v.s", AArch64::ZAS3
)
2606 .Case("za0v.h", AArch64::ZAH0
)
2607 .Case("za1v.h", AArch64::ZAH1
)
2608 .Case("za0v.b", AArch64::ZAB0
)
2612 bool AArch64AsmParser::ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
,
2614 return tryParseRegister(RegNo
, StartLoc
, EndLoc
) != MatchOperand_Success
;
2617 OperandMatchResultTy
AArch64AsmParser::tryParseRegister(unsigned &RegNo
,
2620 StartLoc
= getLoc();
2621 auto Res
= tryParseScalarRegister(RegNo
);
2622 EndLoc
= SMLoc::getFromPointer(getLoc().getPointer() - 1);
2626 // Matches a register name or register alias previously defined by '.req'
2627 unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name
,
2629 unsigned RegNum
= 0;
2630 if ((RegNum
= matchSVEDataVectorRegName(Name
)))
2631 return Kind
== RegKind::SVEDataVector
? RegNum
: 0;
2633 if ((RegNum
= matchSVEPredicateVectorRegName(Name
)))
2634 return Kind
== RegKind::SVEPredicateVector
? RegNum
: 0;
2636 if ((RegNum
= MatchNeonVectorRegName(Name
)))
2637 return Kind
== RegKind::NeonVector
? RegNum
: 0;
2639 if ((RegNum
= matchMatrixRegName(Name
)))
2640 return Kind
== RegKind::Matrix
? RegNum
: 0;
2642 // The parsed register must be of RegKind Scalar
2643 if ((RegNum
= MatchRegisterName(Name
)))
2644 return Kind
== RegKind::Scalar
? RegNum
: 0;
2647 // Handle a few common aliases of registers.
2648 if (auto RegNum
= StringSwitch
<unsigned>(Name
.lower())
2649 .Case("fp", AArch64::FP
)
2650 .Case("lr", AArch64::LR
)
2651 .Case("x31", AArch64::XZR
)
2652 .Case("w31", AArch64::WZR
)
2654 return Kind
== RegKind::Scalar
? RegNum
: 0;
2656 // Check for aliases registered via .req. Canonicalize to lower case.
2657 // That's more consistent since register names are case insensitive, and
2658 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2659 auto Entry
= RegisterReqs
.find(Name
.lower());
2660 if (Entry
== RegisterReqs
.end())
2663 // set RegNum if the match is the right kind of register
2664 if (Kind
== Entry
->getValue().first
)
2665 RegNum
= Entry
->getValue().second
;
2670 /// tryParseScalarRegister - Try to parse a register name. The token must be an
2671 /// Identifier when called, and if it is a register name the token is eaten and
2672 /// the register is added to the operand list.
2673 OperandMatchResultTy
2674 AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum
) {
2675 const AsmToken
&Tok
= getTok();
2676 if (Tok
.isNot(AsmToken::Identifier
))
2677 return MatchOperand_NoMatch
;
2679 std::string lowerCase
= Tok
.getString().lower();
2680 unsigned Reg
= matchRegisterNameAlias(lowerCase
, RegKind::Scalar
);
2682 return MatchOperand_NoMatch
;
2685 Lex(); // Eat identifier token.
2686 return MatchOperand_Success
;
2689 /// tryParseSysCROperand - Try to parse a system instruction CR operand name.
2690 OperandMatchResultTy
2691 AArch64AsmParser::tryParseSysCROperand(OperandVector
&Operands
) {
2694 if (getTok().isNot(AsmToken::Identifier
)) {
2695 Error(S
, "Expected cN operand where 0 <= N <= 15");
2696 return MatchOperand_ParseFail
;
2699 StringRef Tok
= getTok().getIdentifier();
2700 if (Tok
[0] != 'c' && Tok
[0] != 'C') {
2701 Error(S
, "Expected cN operand where 0 <= N <= 15");
2702 return MatchOperand_ParseFail
;
2706 bool BadNum
= Tok
.drop_front().getAsInteger(10, CRNum
);
2707 if (BadNum
|| CRNum
> 15) {
2708 Error(S
, "Expected cN operand where 0 <= N <= 15");
2709 return MatchOperand_ParseFail
;
2712 Lex(); // Eat identifier token.
2714 AArch64Operand::CreateSysCR(CRNum
, S
, getLoc(), getContext()));
2715 return MatchOperand_Success
;
2718 /// tryParsePrefetch - Try to parse a prefetch operand.
2719 template <bool IsSVEPrefetch
>
2720 OperandMatchResultTy
2721 AArch64AsmParser::tryParsePrefetch(OperandVector
&Operands
) {
2723 const AsmToken
&Tok
= getTok();
2725 auto LookupByName
= [](StringRef N
) {
2726 if (IsSVEPrefetch
) {
2727 if (auto Res
= AArch64SVEPRFM::lookupSVEPRFMByName(N
))
2728 return Optional
<unsigned>(Res
->Encoding
);
2729 } else if (auto Res
= AArch64PRFM::lookupPRFMByName(N
))
2730 return Optional
<unsigned>(Res
->Encoding
);
2731 return Optional
<unsigned>();
2734 auto LookupByEncoding
= [](unsigned E
) {
2735 if (IsSVEPrefetch
) {
2736 if (auto Res
= AArch64SVEPRFM::lookupSVEPRFMByEncoding(E
))
2737 return Optional
<StringRef
>(Res
->Name
);
2738 } else if (auto Res
= AArch64PRFM::lookupPRFMByEncoding(E
))
2739 return Optional
<StringRef
>(Res
->Name
);
2740 return Optional
<StringRef
>();
2742 unsigned MaxVal
= IsSVEPrefetch
? 15 : 31;
2744 // Either an identifier for named values or a 5-bit immediate.
2745 // Eat optional hash.
2746 if (parseOptionalToken(AsmToken::Hash
) ||
2747 Tok
.is(AsmToken::Integer
)) {
2748 const MCExpr
*ImmVal
;
2749 if (getParser().parseExpression(ImmVal
))
2750 return MatchOperand_ParseFail
;
2752 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(ImmVal
);
2754 TokError("immediate value expected for prefetch operand");
2755 return MatchOperand_ParseFail
;
2757 unsigned prfop
= MCE
->getValue();
2758 if (prfop
> MaxVal
) {
2759 TokError("prefetch operand out of range, [0," + utostr(MaxVal
) +
2761 return MatchOperand_ParseFail
;
2764 auto PRFM
= LookupByEncoding(MCE
->getValue());
2765 Operands
.push_back(AArch64Operand::CreatePrefetch(
2766 prfop
, PRFM
.getValueOr(""), S
, getContext()));
2767 return MatchOperand_Success
;
2770 if (Tok
.isNot(AsmToken::Identifier
)) {
2771 TokError("prefetch hint expected");
2772 return MatchOperand_ParseFail
;
2775 auto PRFM
= LookupByName(Tok
.getString());
2777 TokError("prefetch hint expected");
2778 return MatchOperand_ParseFail
;
2781 Operands
.push_back(AArch64Operand::CreatePrefetch(
2782 *PRFM
, Tok
.getString(), S
, getContext()));
2783 Lex(); // Eat identifier token.
2784 return MatchOperand_Success
;
2787 /// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
2788 OperandMatchResultTy
2789 AArch64AsmParser::tryParsePSBHint(OperandVector
&Operands
) {
2791 const AsmToken
&Tok
= getTok();
2792 if (Tok
.isNot(AsmToken::Identifier
)) {
2793 TokError("invalid operand for instruction");
2794 return MatchOperand_ParseFail
;
2797 auto PSB
= AArch64PSBHint::lookupPSBByName(Tok
.getString());
2799 TokError("invalid operand for instruction");
2800 return MatchOperand_ParseFail
;
2803 Operands
.push_back(AArch64Operand::CreatePSBHint(
2804 PSB
->Encoding
, Tok
.getString(), S
, getContext()));
2805 Lex(); // Eat identifier token.
2806 return MatchOperand_Success
;
2809 /// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
2810 OperandMatchResultTy
2811 AArch64AsmParser::tryParseBTIHint(OperandVector
&Operands
) {
2813 const AsmToken
&Tok
= getTok();
2814 if (Tok
.isNot(AsmToken::Identifier
)) {
2815 TokError("invalid operand for instruction");
2816 return MatchOperand_ParseFail
;
2819 auto BTI
= AArch64BTIHint::lookupBTIByName(Tok
.getString());
2821 TokError("invalid operand for instruction");
2822 return MatchOperand_ParseFail
;
2825 Operands
.push_back(AArch64Operand::CreateBTIHint(
2826 BTI
->Encoding
, Tok
.getString(), S
, getContext()));
2827 Lex(); // Eat identifier token.
2828 return MatchOperand_Success
;
2831 /// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2833 OperandMatchResultTy
2834 AArch64AsmParser::tryParseAdrpLabel(OperandVector
&Operands
) {
2836 const MCExpr
*Expr
= nullptr;
2838 if (getTok().is(AsmToken::Hash
)) {
2839 Lex(); // Eat hash token.
2842 if (parseSymbolicImmVal(Expr
))
2843 return MatchOperand_ParseFail
;
2845 AArch64MCExpr::VariantKind ELFRefKind
;
2846 MCSymbolRefExpr::VariantKind DarwinRefKind
;
2848 if (classifySymbolRef(Expr
, ELFRefKind
, DarwinRefKind
, Addend
)) {
2849 if (DarwinRefKind
== MCSymbolRefExpr::VK_None
&&
2850 ELFRefKind
== AArch64MCExpr::VK_INVALID
) {
2851 // No modifier was specified at all; this is the syntax for an ELF basic
2852 // ADRP relocation (unfortunately).
2854 AArch64MCExpr::create(Expr
, AArch64MCExpr::VK_ABS_PAGE
, getContext());
2855 } else if ((DarwinRefKind
== MCSymbolRefExpr::VK_GOTPAGE
||
2856 DarwinRefKind
== MCSymbolRefExpr::VK_TLVPPAGE
) &&
2858 Error(S
, "gotpage label reference not allowed an addend");
2859 return MatchOperand_ParseFail
;
2860 } else if (DarwinRefKind
!= MCSymbolRefExpr::VK_PAGE
&&
2861 DarwinRefKind
!= MCSymbolRefExpr::VK_GOTPAGE
&&
2862 DarwinRefKind
!= MCSymbolRefExpr::VK_TLVPPAGE
&&
2863 ELFRefKind
!= AArch64MCExpr::VK_ABS_PAGE_NC
&&
2864 ELFRefKind
!= AArch64MCExpr::VK_GOT_PAGE
&&
2865 ELFRefKind
!= AArch64MCExpr::VK_GOT_PAGE_LO15
&&
2866 ELFRefKind
!= AArch64MCExpr::VK_GOTTPREL_PAGE
&&
2867 ELFRefKind
!= AArch64MCExpr::VK_TLSDESC_PAGE
) {
2868 // The operand must be an @page or @gotpage qualified symbolref.
2869 Error(S
, "page or gotpage label reference expected");
2870 return MatchOperand_ParseFail
;
2874 // We have either a label reference possibly with addend or an immediate. The
2875 // addend is a raw value here. The linker will adjust it to only reference the
2877 SMLoc E
= SMLoc::getFromPointer(getLoc().getPointer() - 1);
2878 Operands
.push_back(AArch64Operand::CreateImm(Expr
, S
, E
, getContext()));
2880 return MatchOperand_Success
;
2883 /// tryParseAdrLabel - Parse and validate a source label for the ADR
2885 OperandMatchResultTy
2886 AArch64AsmParser::tryParseAdrLabel(OperandVector
&Operands
) {
2888 const MCExpr
*Expr
= nullptr;
2890 // Leave anything with a bracket to the default for SVE
2891 if (getTok().is(AsmToken::LBrac
))
2892 return MatchOperand_NoMatch
;
2894 if (getTok().is(AsmToken::Hash
))
2895 Lex(); // Eat hash token.
2897 if (parseSymbolicImmVal(Expr
))
2898 return MatchOperand_ParseFail
;
2900 AArch64MCExpr::VariantKind ELFRefKind
;
2901 MCSymbolRefExpr::VariantKind DarwinRefKind
;
2903 if (classifySymbolRef(Expr
, ELFRefKind
, DarwinRefKind
, Addend
)) {
2904 if (DarwinRefKind
== MCSymbolRefExpr::VK_None
&&
2905 ELFRefKind
== AArch64MCExpr::VK_INVALID
) {
2906 // No modifier was specified at all; this is the syntax for an ELF basic
2907 // ADR relocation (unfortunately).
2908 Expr
= AArch64MCExpr::create(Expr
, AArch64MCExpr::VK_ABS
, getContext());
2910 Error(S
, "unexpected adr label");
2911 return MatchOperand_ParseFail
;
2915 SMLoc E
= SMLoc::getFromPointer(getLoc().getPointer() - 1);
2916 Operands
.push_back(AArch64Operand::CreateImm(Expr
, S
, E
, getContext()));
2917 return MatchOperand_Success
;
2920 /// tryParseFPImm - A floating point immediate expression operand.
2921 template<bool AddFPZeroAsLiteral
>
2922 OperandMatchResultTy
2923 AArch64AsmParser::tryParseFPImm(OperandVector
&Operands
) {
2926 bool Hash
= parseOptionalToken(AsmToken::Hash
);
2928 // Handle negation, as that still comes through as a separate token.
2929 bool isNegative
= parseOptionalToken(AsmToken::Minus
);
2931 const AsmToken
&Tok
= getTok();
2932 if (!Tok
.is(AsmToken::Real
) && !Tok
.is(AsmToken::Integer
)) {
2934 return MatchOperand_NoMatch
;
2935 TokError("invalid floating point immediate");
2936 return MatchOperand_ParseFail
;
2939 // Parse hexadecimal representation.
2940 if (Tok
.is(AsmToken::Integer
) && Tok
.getString().startswith("0x")) {
2941 if (Tok
.getIntVal() > 255 || isNegative
) {
2942 TokError("encoded floating point value out of range");
2943 return MatchOperand_ParseFail
;
2946 APFloat
F((double)AArch64_AM::getFPImmFloat(Tok
.getIntVal()));
2948 AArch64Operand::CreateFPImm(F
, true, S
, getContext()));
2950 // Parse FP representation.
2951 APFloat
RealVal(APFloat::IEEEdouble());
2953 RealVal
.convertFromString(Tok
.getString(), APFloat::rmTowardZero
);
2954 if (errorToBool(StatusOrErr
.takeError())) {
2955 TokError("invalid floating point representation");
2956 return MatchOperand_ParseFail
;
2960 RealVal
.changeSign();
2962 if (AddFPZeroAsLiteral
&& RealVal
.isPosZero()) {
2963 Operands
.push_back(AArch64Operand::CreateToken("#0", S
, getContext()));
2964 Operands
.push_back(AArch64Operand::CreateToken(".0", S
, getContext()));
2966 Operands
.push_back(AArch64Operand::CreateFPImm(
2967 RealVal
, *StatusOrErr
== APFloat::opOK
, S
, getContext()));
2970 Lex(); // Eat the token.
2972 return MatchOperand_Success
;
2975 /// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2976 /// a shift suffix, for example '#1, lsl #12'.
2977 OperandMatchResultTy
2978 AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector
&Operands
) {
2981 if (getTok().is(AsmToken::Hash
))
2983 else if (getTok().isNot(AsmToken::Integer
))
2984 // Operand should start from # or should be integer, emit error otherwise.
2985 return MatchOperand_NoMatch
;
2987 const MCExpr
*Imm
= nullptr;
2988 if (parseSymbolicImmVal(Imm
))
2989 return MatchOperand_ParseFail
;
2990 else if (getTok().isNot(AsmToken::Comma
)) {
2992 AArch64Operand::CreateImm(Imm
, S
, getLoc(), getContext()));
2993 return MatchOperand_Success
;
2999 // The optional operand must be "lsl #N" where N is non-negative.
3000 if (!getTok().is(AsmToken::Identifier
) ||
3001 !getTok().getIdentifier().equals_insensitive("lsl")) {
3002 Error(getLoc(), "only 'lsl #+N' valid after immediate");
3003 return MatchOperand_ParseFail
;
3009 parseOptionalToken(AsmToken::Hash
);
3011 if (getTok().isNot(AsmToken::Integer
)) {
3012 Error(getLoc(), "only 'lsl #+N' valid after immediate");
3013 return MatchOperand_ParseFail
;
3016 int64_t ShiftAmount
= getTok().getIntVal();
3018 if (ShiftAmount
< 0) {
3019 Error(getLoc(), "positive shift amount required");
3020 return MatchOperand_ParseFail
;
3022 Lex(); // Eat the number
3024 // Just in case the optional lsl #0 is used for immediates other than zero.
3025 if (ShiftAmount
== 0 && Imm
!= nullptr) {
3027 AArch64Operand::CreateImm(Imm
, S
, getLoc(), getContext()));
3028 return MatchOperand_Success
;
3031 Operands
.push_back(AArch64Operand::CreateShiftedImm(Imm
, ShiftAmount
, S
,
3032 getLoc(), getContext()));
3033 return MatchOperand_Success
;
3036 /// parseCondCodeString - Parse a Condition Code string.
3037 AArch64CC::CondCode
AArch64AsmParser::parseCondCodeString(StringRef Cond
) {
3038 AArch64CC::CondCode CC
= StringSwitch
<AArch64CC::CondCode
>(Cond
.lower())
3039 .Case("eq", AArch64CC::EQ
)
3040 .Case("ne", AArch64CC::NE
)
3041 .Case("cs", AArch64CC::HS
)
3042 .Case("hs", AArch64CC::HS
)
3043 .Case("cc", AArch64CC::LO
)
3044 .Case("lo", AArch64CC::LO
)
3045 .Case("mi", AArch64CC::MI
)
3046 .Case("pl", AArch64CC::PL
)
3047 .Case("vs", AArch64CC::VS
)
3048 .Case("vc", AArch64CC::VC
)
3049 .Case("hi", AArch64CC::HI
)
3050 .Case("ls", AArch64CC::LS
)
3051 .Case("ge", AArch64CC::GE
)
3052 .Case("lt", AArch64CC::LT
)
3053 .Case("gt", AArch64CC::GT
)
3054 .Case("le", AArch64CC::LE
)
3055 .Case("al", AArch64CC::AL
)
3056 .Case("nv", AArch64CC::NV
)
3057 .Default(AArch64CC::Invalid
);
3059 if (CC
== AArch64CC::Invalid
&&
3060 getSTI().getFeatureBits()[AArch64::FeatureSVE
])
3061 CC
= StringSwitch
<AArch64CC::CondCode
>(Cond
.lower())
3062 .Case("none", AArch64CC::EQ
)
3063 .Case("any", AArch64CC::NE
)
3064 .Case("nlast", AArch64CC::HS
)
3065 .Case("last", AArch64CC::LO
)
3066 .Case("first", AArch64CC::MI
)
3067 .Case("nfrst", AArch64CC::PL
)
3068 .Case("pmore", AArch64CC::HI
)
3069 .Case("plast", AArch64CC::LS
)
3070 .Case("tcont", AArch64CC::GE
)
3071 .Case("tstop", AArch64CC::LT
)
3072 .Default(AArch64CC::Invalid
);
3077 /// parseCondCode - Parse a Condition Code operand.
3078 bool AArch64AsmParser::parseCondCode(OperandVector
&Operands
,
3079 bool invertCondCode
) {
3081 const AsmToken
&Tok
= getTok();
3082 assert(Tok
.is(AsmToken::Identifier
) && "Token is not an Identifier");
3084 StringRef Cond
= Tok
.getString();
3085 AArch64CC::CondCode CC
= parseCondCodeString(Cond
);
3086 if (CC
== AArch64CC::Invalid
)
3087 return TokError("invalid condition code");
3088 Lex(); // Eat identifier token.
3090 if (invertCondCode
) {
3091 if (CC
== AArch64CC::AL
|| CC
== AArch64CC::NV
)
3092 return TokError("condition codes AL and NV are invalid for this instruction");
3093 CC
= AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC
));
3097 AArch64Operand::CreateCondCode(CC
, S
, getLoc(), getContext()));
3101 OperandMatchResultTy
3102 AArch64AsmParser::tryParseSVCR(OperandVector
&Operands
) {
3103 const AsmToken
&Tok
= getTok();
3106 if (Tok
.isNot(AsmToken::Identifier
)) {
3107 TokError("invalid operand for instruction");
3108 return MatchOperand_ParseFail
;
3111 unsigned PStateImm
= -1;
3112 const auto *SVCR
= AArch64SVCR::lookupSVCRByName(Tok
.getString());
3113 if (SVCR
&& SVCR
->haveFeatures(getSTI().getFeatureBits()))
3114 PStateImm
= SVCR
->Encoding
;
3117 AArch64Operand::CreateSVCR(PStateImm
, Tok
.getString(), S
, getContext()));
3118 Lex(); // Eat identifier token.
3119 return MatchOperand_Success
;
3122 OperandMatchResultTy
3123 AArch64AsmParser::tryParseMatrixRegister(OperandVector
&Operands
) {
3124 const AsmToken
&Tok
= getTok();
3127 StringRef Name
= Tok
.getString();
3129 if (Name
.equals_insensitive("za")) {
3131 Operands
.push_back(AArch64Operand::CreateMatrixRegister(
3132 AArch64::ZA
, /*ElementWidth=*/0, MatrixKind::Array
, S
, getLoc(),
3134 if (getLexer().is(AsmToken::LBrac
)) {
3135 // There's no comma after matrix operand, so we can parse the next operand
3137 if (parseOperand(Operands
, false, false))
3138 return MatchOperand_NoMatch
;
3140 return MatchOperand_Success
;
3143 // Try to parse matrix register.
3144 unsigned Reg
= matchRegisterNameAlias(Name
, RegKind::Matrix
);
3146 return MatchOperand_NoMatch
;
3148 size_t DotPosition
= Name
.find('.');
3149 assert(DotPosition
!= StringRef::npos
&& "Unexpected register");
3151 StringRef Head
= Name
.take_front(DotPosition
);
3152 StringRef Tail
= Name
.drop_front(DotPosition
);
3153 StringRef RowOrColumn
= Head
.take_back();
3155 MatrixKind Kind
= StringSwitch
<MatrixKind
>(RowOrColumn
)
3156 .Case("h", MatrixKind::Row
)
3157 .Case("v", MatrixKind::Col
)
3158 .Default(MatrixKind::Tile
);
3160 // Next up, parsing the suffix
3161 const auto &KindRes
= parseVectorKind(Tail
, RegKind::Matrix
);
3163 TokError("Expected the register to be followed by element width suffix");
3164 return MatchOperand_ParseFail
;
3166 unsigned ElementWidth
= KindRes
->second
;
3170 Operands
.push_back(AArch64Operand::CreateMatrixRegister(
3171 Reg
, ElementWidth
, Kind
, S
, getLoc(), getContext()));
3173 if (getLexer().is(AsmToken::LBrac
)) {
3174 // There's no comma after matrix operand, so we can parse the next operand
3176 if (parseOperand(Operands
, false, false))
3177 return MatchOperand_NoMatch
;
3179 return MatchOperand_Success
;
3182 /// tryParseOptionalShift - Some operands take an optional shift argument. Parse
3183 /// them if present.
3184 OperandMatchResultTy
3185 AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector
&Operands
) {
3186 const AsmToken
&Tok
= getTok();
3187 std::string LowerID
= Tok
.getString().lower();
3188 AArch64_AM::ShiftExtendType ShOp
=
3189 StringSwitch
<AArch64_AM::ShiftExtendType
>(LowerID
)
3190 .Case("lsl", AArch64_AM::LSL
)
3191 .Case("lsr", AArch64_AM::LSR
)
3192 .Case("asr", AArch64_AM::ASR
)
3193 .Case("ror", AArch64_AM::ROR
)
3194 .Case("msl", AArch64_AM::MSL
)
3195 .Case("uxtb", AArch64_AM::UXTB
)
3196 .Case("uxth", AArch64_AM::UXTH
)
3197 .Case("uxtw", AArch64_AM::UXTW
)
3198 .Case("uxtx", AArch64_AM::UXTX
)
3199 .Case("sxtb", AArch64_AM::SXTB
)
3200 .Case("sxth", AArch64_AM::SXTH
)
3201 .Case("sxtw", AArch64_AM::SXTW
)
3202 .Case("sxtx", AArch64_AM::SXTX
)
3203 .Default(AArch64_AM::InvalidShiftExtend
);
3205 if (ShOp
== AArch64_AM::InvalidShiftExtend
)
3206 return MatchOperand_NoMatch
;
3208 SMLoc S
= Tok
.getLoc();
3211 bool Hash
= parseOptionalToken(AsmToken::Hash
);
3213 if (!Hash
&& getLexer().isNot(AsmToken::Integer
)) {
3214 if (ShOp
== AArch64_AM::LSL
|| ShOp
== AArch64_AM::LSR
||
3215 ShOp
== AArch64_AM::ASR
|| ShOp
== AArch64_AM::ROR
||
3216 ShOp
== AArch64_AM::MSL
) {
3217 // We expect a number here.
3218 TokError("expected #imm after shift specifier");
3219 return MatchOperand_ParseFail
;
3222 // "extend" type operations don't need an immediate, #0 is implicit.
3223 SMLoc E
= SMLoc::getFromPointer(getLoc().getPointer() - 1);
3225 AArch64Operand::CreateShiftExtend(ShOp
, 0, false, S
, E
, getContext()));
3226 return MatchOperand_Success
;
3229 // Make sure we do actually have a number, identifier or a parenthesized
3232 if (!getTok().is(AsmToken::Integer
) && !getTok().is(AsmToken::LParen
) &&
3233 !getTok().is(AsmToken::Identifier
)) {
3234 Error(E
, "expected integer shift amount");
3235 return MatchOperand_ParseFail
;
3238 const MCExpr
*ImmVal
;
3239 if (getParser().parseExpression(ImmVal
))
3240 return MatchOperand_ParseFail
;
3242 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(ImmVal
);
3244 Error(E
, "expected constant '#imm' after shift specifier");
3245 return MatchOperand_ParseFail
;
3248 E
= SMLoc::getFromPointer(getLoc().getPointer() - 1);
3249 Operands
.push_back(AArch64Operand::CreateShiftExtend(
3250 ShOp
, MCE
->getValue(), true, S
, E
, getContext()));
3251 return MatchOperand_Success
;
3254 static const struct Extension
{
3256 const FeatureBitset Features
;
3257 } ExtensionMap
[] = {
3258 {"crc", {AArch64::FeatureCRC
}},
3259 {"sm4", {AArch64::FeatureSM4
}},
3260 {"sha3", {AArch64::FeatureSHA3
}},
3261 {"sha2", {AArch64::FeatureSHA2
}},
3262 {"aes", {AArch64::FeatureAES
}},
3263 {"crypto", {AArch64::FeatureCrypto
}},
3264 {"fp", {AArch64::FeatureFPARMv8
}},
3265 {"simd", {AArch64::FeatureNEON
}},
3266 {"ras", {AArch64::FeatureRAS
}},
3267 {"lse", {AArch64::FeatureLSE
}},
3268 {"predres", {AArch64::FeaturePredRes
}},
3269 {"ccdp", {AArch64::FeatureCacheDeepPersist
}},
3270 {"mte", {AArch64::FeatureMTE
}},
3271 {"memtag", {AArch64::FeatureMTE
}},
3272 {"tlb-rmi", {AArch64::FeatureTLB_RMI
}},
3273 {"pan", {AArch64::FeaturePAN
}},
3274 {"pan-rwv", {AArch64::FeaturePAN_RWV
}},
3275 {"ccpp", {AArch64::FeatureCCPP
}},
3276 {"rcpc", {AArch64::FeatureRCPC
}},
3277 {"rng", {AArch64::FeatureRandGen
}},
3278 {"sve", {AArch64::FeatureSVE
}},
3279 {"sve2", {AArch64::FeatureSVE2
}},
3280 {"sve2-aes", {AArch64::FeatureSVE2AES
}},
3281 {"sve2-sm4", {AArch64::FeatureSVE2SM4
}},
3282 {"sve2-sha3", {AArch64::FeatureSVE2SHA3
}},
3283 {"sve2-bitperm", {AArch64::FeatureSVE2BitPerm
}},
3284 {"ls64", {AArch64::FeatureLS64
}},
3285 {"xs", {AArch64::FeatureXS
}},
3286 {"pauth", {AArch64::FeaturePAuth
}},
3287 {"flagm", {AArch64::FeatureFlagM
}},
3288 {"rme", {AArch64::FeatureRME
}},
3289 {"sme", {AArch64::FeatureSME
}},
3290 {"sme-f64", {AArch64::FeatureSMEF64
}},
3291 {"sme-i64", {AArch64::FeatureSMEI64
}},
3292 // FIXME: Unsupported extensions
3298 static void setRequiredFeatureString(FeatureBitset FBS
, std::string
&Str
) {
3299 if (FBS
[AArch64::HasV8_1aOps
])
3301 else if (FBS
[AArch64::HasV8_2aOps
])
3303 else if (FBS
[AArch64::HasV8_3aOps
])
3305 else if (FBS
[AArch64::HasV8_4aOps
])
3307 else if (FBS
[AArch64::HasV8_5aOps
])
3309 else if (FBS
[AArch64::HasV8_6aOps
])
3311 else if (FBS
[AArch64::HasV8_7aOps
])
3314 SmallVector
<std::string
, 2> ExtMatches
;
3315 for (const auto& Ext
: ExtensionMap
) {
3316 // Use & in case multiple features are enabled
3317 if ((FBS
& Ext
.Features
) != FeatureBitset())
3318 ExtMatches
.push_back(Ext
.Name
);
3320 Str
+= !ExtMatches
.empty() ? llvm::join(ExtMatches
, ", ") : "(unknown)";
3324 void AArch64AsmParser::createSysAlias(uint16_t Encoding
, OperandVector
&Operands
,
3326 const uint16_t Op2
= Encoding
& 7;
3327 const uint16_t Cm
= (Encoding
& 0x78) >> 3;
3328 const uint16_t Cn
= (Encoding
& 0x780) >> 7;
3329 const uint16_t Op1
= (Encoding
& 0x3800) >> 11;
3331 const MCExpr
*Expr
= MCConstantExpr::create(Op1
, getContext());
3334 AArch64Operand::CreateImm(Expr
, S
, getLoc(), getContext()));
3336 AArch64Operand::CreateSysCR(Cn
, S
, getLoc(), getContext()));
3338 AArch64Operand::CreateSysCR(Cm
, S
, getLoc(), getContext()));
3339 Expr
= MCConstantExpr::create(Op2
, getContext());
3341 AArch64Operand::CreateImm(Expr
, S
, getLoc(), getContext()));
3344 /// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
3345 /// the SYS instruction. Parse them specially so that we create a SYS MCInst.
3346 bool AArch64AsmParser::parseSysAlias(StringRef Name
, SMLoc NameLoc
,
3347 OperandVector
&Operands
) {
3348 if (Name
.find('.') != StringRef::npos
)
3349 return TokError("invalid operand");
3352 Operands
.push_back(AArch64Operand::CreateToken("sys", NameLoc
, getContext()));
3354 const AsmToken
&Tok
= getTok();
3355 StringRef Op
= Tok
.getString();
3356 SMLoc S
= Tok
.getLoc();
3358 if (Mnemonic
== "ic") {
3359 const AArch64IC::IC
*IC
= AArch64IC::lookupICByName(Op
);
3361 return TokError("invalid operand for IC instruction");
3362 else if (!IC
->haveFeatures(getSTI().getFeatureBits())) {
3363 std::string
Str("IC " + std::string(IC
->Name
) + " requires: ");
3364 setRequiredFeatureString(IC
->getRequiredFeatures(), Str
);
3365 return TokError(Str
);
3367 createSysAlias(IC
->Encoding
, Operands
, S
);
3368 } else if (Mnemonic
== "dc") {
3369 const AArch64DC::DC
*DC
= AArch64DC::lookupDCByName(Op
);
3371 return TokError("invalid operand for DC instruction");
3372 else if (!DC
->haveFeatures(getSTI().getFeatureBits())) {
3373 std::string
Str("DC " + std::string(DC
->Name
) + " requires: ");
3374 setRequiredFeatureString(DC
->getRequiredFeatures(), Str
);
3375 return TokError(Str
);
3377 createSysAlias(DC
->Encoding
, Operands
, S
);
3378 } else if (Mnemonic
== "at") {
3379 const AArch64AT::AT
*AT
= AArch64AT::lookupATByName(Op
);
3381 return TokError("invalid operand for AT instruction");
3382 else if (!AT
->haveFeatures(getSTI().getFeatureBits())) {
3383 std::string
Str("AT " + std::string(AT
->Name
) + " requires: ");
3384 setRequiredFeatureString(AT
->getRequiredFeatures(), Str
);
3385 return TokError(Str
);
3387 createSysAlias(AT
->Encoding
, Operands
, S
);
3388 } else if (Mnemonic
== "tlbi") {
3389 const AArch64TLBI::TLBI
*TLBI
= AArch64TLBI::lookupTLBIByName(Op
);
3391 return TokError("invalid operand for TLBI instruction");
3392 else if (!TLBI
->haveFeatures(getSTI().getFeatureBits())) {
3393 std::string
Str("TLBI " + std::string(TLBI
->Name
) + " requires: ");
3394 setRequiredFeatureString(TLBI
->getRequiredFeatures(), Str
);
3395 return TokError(Str
);
3397 createSysAlias(TLBI
->Encoding
, Operands
, S
);
3398 } else if (Mnemonic
== "cfp" || Mnemonic
== "dvp" || Mnemonic
== "cpp") {
3399 const AArch64PRCTX::PRCTX
*PRCTX
= AArch64PRCTX::lookupPRCTXByName(Op
);
3401 return TokError("invalid operand for prediction restriction instruction");
3402 else if (!PRCTX
->haveFeatures(getSTI().getFeatureBits())) {
3404 Mnemonic
.upper() + std::string(PRCTX
->Name
) + " requires: ");
3405 setRequiredFeatureString(PRCTX
->getRequiredFeatures(), Str
);
3406 return TokError(Str
);
3408 uint16_t PRCTX_Op2
=
3409 Mnemonic
== "cfp" ? 4 :
3410 Mnemonic
== "dvp" ? 5 :
3411 Mnemonic
== "cpp" ? 7 :
3413 assert(PRCTX_Op2
&& "Invalid mnemonic for prediction restriction instruction");
3414 createSysAlias(PRCTX
->Encoding
<< 3 | PRCTX_Op2
, Operands
, S
);
3417 Lex(); // Eat operand.
3419 bool ExpectRegister
= (Op
.lower().find("all") == StringRef::npos
);
3420 bool HasRegister
= false;
3422 // Check for the optional register operand.
3423 if (parseOptionalToken(AsmToken::Comma
)) {
3424 if (Tok
.isNot(AsmToken::Identifier
) || parseRegister(Operands
))
3425 return TokError("expected register operand");
3429 if (ExpectRegister
&& !HasRegister
)
3430 return TokError("specified " + Mnemonic
+ " op requires a register");
3431 else if (!ExpectRegister
&& HasRegister
)
3432 return TokError("specified " + Mnemonic
+ " op does not use a register");
3434 if (parseToken(AsmToken::EndOfStatement
, "unexpected token in argument list"))
3440 OperandMatchResultTy
3441 AArch64AsmParser::tryParseBarrierOperand(OperandVector
&Operands
) {
3442 MCAsmParser
&Parser
= getParser();
3443 const AsmToken
&Tok
= getTok();
3445 if (Mnemonic
== "tsb" && Tok
.isNot(AsmToken::Identifier
)) {
3446 TokError("'csync' operand expected");
3447 return MatchOperand_ParseFail
;
3448 } else if (parseOptionalToken(AsmToken::Hash
) || Tok
.is(AsmToken::Integer
)) {
3449 // Immediate operand.
3450 const MCExpr
*ImmVal
;
3451 SMLoc ExprLoc
= getLoc();
3452 AsmToken IntTok
= Tok
;
3453 if (getParser().parseExpression(ImmVal
))
3454 return MatchOperand_ParseFail
;
3455 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(ImmVal
);
3457 Error(ExprLoc
, "immediate value expected for barrier operand");
3458 return MatchOperand_ParseFail
;
3460 int64_t Value
= MCE
->getValue();
3461 if (Mnemonic
== "dsb" && Value
> 15) {
3462 // This case is a no match here, but it might be matched by the nXS
3463 // variant. Deliberately not unlex the optional '#' as it is not necessary
3464 // to characterize an integer immediate.
3465 Parser
.getLexer().UnLex(IntTok
);
3466 return MatchOperand_NoMatch
;
3468 if (Value
< 0 || Value
> 15) {
3469 Error(ExprLoc
, "barrier operand out of range");
3470 return MatchOperand_ParseFail
;
3472 auto DB
= AArch64DB::lookupDBByEncoding(Value
);
3473 Operands
.push_back(AArch64Operand::CreateBarrier(Value
, DB
? DB
->Name
: "",
3474 ExprLoc
, getContext(),
3475 false /*hasnXSModifier*/));
3476 return MatchOperand_Success
;
3479 if (Tok
.isNot(AsmToken::Identifier
)) {
3480 TokError("invalid operand for instruction");
3481 return MatchOperand_ParseFail
;
3484 StringRef Operand
= Tok
.getString();
3485 auto TSB
= AArch64TSB::lookupTSBByName(Operand
);
3486 auto DB
= AArch64DB::lookupDBByName(Operand
);
3487 // The only valid named option for ISB is 'sy'
3488 if (Mnemonic
== "isb" && (!DB
|| DB
->Encoding
!= AArch64DB::sy
)) {
3489 TokError("'sy' or #imm operand expected");
3490 return MatchOperand_ParseFail
;
3491 // The only valid named option for TSB is 'csync'
3492 } else if (Mnemonic
== "tsb" && (!TSB
|| TSB
->Encoding
!= AArch64TSB::csync
)) {
3493 TokError("'csync' operand expected");
3494 return MatchOperand_ParseFail
;
3495 } else if (!DB
&& !TSB
) {
3496 if (Mnemonic
== "dsb") {
3497 // This case is a no match here, but it might be matched by the nXS
3499 return MatchOperand_NoMatch
;
3501 TokError("invalid barrier option name");
3502 return MatchOperand_ParseFail
;
3505 Operands
.push_back(AArch64Operand::CreateBarrier(
3506 DB
? DB
->Encoding
: TSB
->Encoding
, Tok
.getString(), getLoc(),
3507 getContext(), false /*hasnXSModifier*/));
3508 Lex(); // Consume the option
3510 return MatchOperand_Success
;
3513 OperandMatchResultTy
3514 AArch64AsmParser::tryParseBarriernXSOperand(OperandVector
&Operands
) {
3515 const AsmToken
&Tok
= getTok();
3517 assert(Mnemonic
== "dsb" && "Instruction does not accept nXS operands");
3518 if (Mnemonic
!= "dsb")
3519 return MatchOperand_ParseFail
;
3521 if (parseOptionalToken(AsmToken::Hash
) || Tok
.is(AsmToken::Integer
)) {
3522 // Immediate operand.
3523 const MCExpr
*ImmVal
;
3524 SMLoc ExprLoc
= getLoc();
3525 if (getParser().parseExpression(ImmVal
))
3526 return MatchOperand_ParseFail
;
3527 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(ImmVal
);
3529 Error(ExprLoc
, "immediate value expected for barrier operand");
3530 return MatchOperand_ParseFail
;
3532 int64_t Value
= MCE
->getValue();
3533 // v8.7-A DSB in the nXS variant accepts only the following immediate
3534 // values: 16, 20, 24, 28.
3535 if (Value
!= 16 && Value
!= 20 && Value
!= 24 && Value
!= 28) {
3536 Error(ExprLoc
, "barrier operand out of range");
3537 return MatchOperand_ParseFail
;
3539 auto DB
= AArch64DBnXS::lookupDBnXSByImmValue(Value
);
3540 Operands
.push_back(AArch64Operand::CreateBarrier(DB
->Encoding
, DB
->Name
,
3541 ExprLoc
, getContext(),
3542 true /*hasnXSModifier*/));
3543 return MatchOperand_Success
;
3546 if (Tok
.isNot(AsmToken::Identifier
)) {
3547 TokError("invalid operand for instruction");
3548 return MatchOperand_ParseFail
;
3551 StringRef Operand
= Tok
.getString();
3552 auto DB
= AArch64DBnXS::lookupDBnXSByName(Operand
);
3555 TokError("invalid barrier option name");
3556 return MatchOperand_ParseFail
;
3560 AArch64Operand::CreateBarrier(DB
->Encoding
, Tok
.getString(), getLoc(),
3561 getContext(), true /*hasnXSModifier*/));
3562 Lex(); // Consume the option
3564 return MatchOperand_Success
;
3567 OperandMatchResultTy
3568 AArch64AsmParser::tryParseSysReg(OperandVector
&Operands
) {
3569 const AsmToken
&Tok
= getTok();
3571 if (Tok
.isNot(AsmToken::Identifier
))
3572 return MatchOperand_NoMatch
;
3574 if (AArch64SVCR::lookupSVCRByName(Tok
.getString()))
3575 return MatchOperand_NoMatch
;
3578 auto SysReg
= AArch64SysReg::lookupSysRegByName(Tok
.getString());
3579 if (SysReg
&& SysReg
->haveFeatures(getSTI().getFeatureBits())) {
3580 MRSReg
= SysReg
->Readable
? SysReg
->Encoding
: -1;
3581 MSRReg
= SysReg
->Writeable
? SysReg
->Encoding
: -1;
3583 MRSReg
= MSRReg
= AArch64SysReg::parseGenericRegister(Tok
.getString());
3585 auto PState
= AArch64PState::lookupPStateByName(Tok
.getString());
3586 unsigned PStateImm
= -1;
3587 if (PState
&& PState
->haveFeatures(getSTI().getFeatureBits()))
3588 PStateImm
= PState
->Encoding
;
3591 AArch64Operand::CreateSysReg(Tok
.getString(), getLoc(), MRSReg
, MSRReg
,
3592 PStateImm
, getContext()));
3593 Lex(); // Eat identifier
3595 return MatchOperand_Success
;
3598 /// tryParseNeonVectorRegister - Parse a vector register operand.
3599 bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector
&Operands
) {
3600 if (getTok().isNot(AsmToken::Identifier
))
3604 // Check for a vector register specifier first.
3607 OperandMatchResultTy Res
=
3608 tryParseVectorRegister(Reg
, Kind
, RegKind::NeonVector
);
3609 if (Res
!= MatchOperand_Success
)
3612 const auto &KindRes
= parseVectorKind(Kind
, RegKind::NeonVector
);
3616 unsigned ElementWidth
= KindRes
->second
;
3618 AArch64Operand::CreateVectorReg(Reg
, RegKind::NeonVector
, ElementWidth
,
3619 S
, getLoc(), getContext()));
3621 // If there was an explicit qualifier, that goes on as a literal text
3624 Operands
.push_back(AArch64Operand::CreateToken(Kind
, S
, getContext()));
3626 return tryParseVectorIndex(Operands
) == MatchOperand_ParseFail
;
3629 OperandMatchResultTy
3630 AArch64AsmParser::tryParseVectorIndex(OperandVector
&Operands
) {
3631 SMLoc SIdx
= getLoc();
3632 if (parseOptionalToken(AsmToken::LBrac
)) {
3633 const MCExpr
*ImmVal
;
3634 if (getParser().parseExpression(ImmVal
))
3635 return MatchOperand_NoMatch
;
3636 const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(ImmVal
);
3638 TokError("immediate value expected for vector index");
3639 return MatchOperand_ParseFail
;;
3644 if (parseToken(AsmToken::RBrac
, "']' expected"))
3645 return MatchOperand_ParseFail
;;
3647 Operands
.push_back(AArch64Operand::CreateVectorIndex(MCE
->getValue(), SIdx
,
3649 return MatchOperand_Success
;
3652 return MatchOperand_NoMatch
;
3655 // tryParseVectorRegister - Try to parse a vector register name with
3656 // optional kind specifier. If it is a register specifier, eat the token
3658 OperandMatchResultTy
3659 AArch64AsmParser::tryParseVectorRegister(unsigned &Reg
, StringRef
&Kind
,
3660 RegKind MatchKind
) {
3661 const AsmToken
&Tok
= getTok();
3663 if (Tok
.isNot(AsmToken::Identifier
))
3664 return MatchOperand_NoMatch
;
3666 StringRef Name
= Tok
.getString();
3667 // If there is a kind specifier, it's separated from the register name by
3669 size_t Start
= 0, Next
= Name
.find('.');
3670 StringRef Head
= Name
.slice(Start
, Next
);
3671 unsigned RegNum
= matchRegisterNameAlias(Head
, MatchKind
);
3674 if (Next
!= StringRef::npos
) {
3675 Kind
= Name
.slice(Next
, StringRef::npos
);
3676 if (!isValidVectorKind(Kind
, MatchKind
)) {
3677 TokError("invalid vector kind qualifier");
3678 return MatchOperand_ParseFail
;
3681 Lex(); // Eat the register token.
3684 return MatchOperand_Success
;
3687 return MatchOperand_NoMatch
;
3690 /// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3691 OperandMatchResultTy
3692 AArch64AsmParser::tryParseSVEPredicateVector(OperandVector
&Operands
) {
3693 // Check for a SVE predicate register specifier first.
3694 const SMLoc S
= getLoc();
3697 auto Res
= tryParseVectorRegister(RegNum
, Kind
, RegKind::SVEPredicateVector
);
3698 if (Res
!= MatchOperand_Success
)
3701 const auto &KindRes
= parseVectorKind(Kind
, RegKind::SVEPredicateVector
);
3703 return MatchOperand_NoMatch
;
3705 unsigned ElementWidth
= KindRes
->second
;
3706 Operands
.push_back(AArch64Operand::CreateVectorReg(
3707 RegNum
, RegKind::SVEPredicateVector
, ElementWidth
, S
,
3708 getLoc(), getContext()));
3710 if (getLexer().is(AsmToken::LBrac
)) {
3711 // Indexed predicate, there's no comma so try parse the next operand
3713 if (parseOperand(Operands
, false, false))
3714 return MatchOperand_NoMatch
;
3717 // Not all predicates are followed by a '/m' or '/z'.
3718 if (getTok().isNot(AsmToken::Slash
))
3719 return MatchOperand_Success
;
3721 // But when they do they shouldn't have an element type suffix.
3722 if (!Kind
.empty()) {
3723 Error(S
, "not expecting size suffix");
3724 return MatchOperand_ParseFail
;
3727 // Add a literal slash as operand
3728 Operands
.push_back(AArch64Operand::CreateToken("/", getLoc(), getContext()));
3730 Lex(); // Eat the slash.
3732 // Zeroing or merging?
3733 auto Pred
= getTok().getString().lower();
3734 if (Pred
!= "z" && Pred
!= "m") {
3735 Error(getLoc(), "expecting 'm' or 'z' predication");
3736 return MatchOperand_ParseFail
;
3739 // Add zero/merge token.
3740 const char *ZM
= Pred
== "z" ? "z" : "m";
3741 Operands
.push_back(AArch64Operand::CreateToken(ZM
, getLoc(), getContext()));
3743 Lex(); // Eat zero/merge token.
3744 return MatchOperand_Success
;
3747 /// parseRegister - Parse a register operand.
3748 bool AArch64AsmParser::parseRegister(OperandVector
&Operands
) {
3749 // Try for a Neon vector register.
3750 if (!tryParseNeonVectorRegister(Operands
))
3753 // Otherwise try for a scalar register.
3754 if (tryParseGPROperand
<false>(Operands
) == MatchOperand_Success
)
3760 bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr
*&ImmVal
) {
3761 bool HasELFModifier
= false;
3762 AArch64MCExpr::VariantKind RefKind
;
3764 if (parseOptionalToken(AsmToken::Colon
)) {
3765 HasELFModifier
= true;
3767 if (getTok().isNot(AsmToken::Identifier
))
3768 return TokError("expect relocation specifier in operand after ':'");
3770 std::string LowerCase
= getTok().getIdentifier().lower();
3771 RefKind
= StringSwitch
<AArch64MCExpr::VariantKind
>(LowerCase
)
3772 .Case("lo12", AArch64MCExpr::VK_LO12
)
3773 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3
)
3774 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2
)
3775 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S
)
3776 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC
)
3777 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1
)
3778 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S
)
3779 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC
)
3780 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0
)
3781 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S
)
3782 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC
)
3783 .Case("prel_g3", AArch64MCExpr::VK_PREL_G3
)
3784 .Case("prel_g2", AArch64MCExpr::VK_PREL_G2
)
3785 .Case("prel_g2_nc", AArch64MCExpr::VK_PREL_G2_NC
)
3786 .Case("prel_g1", AArch64MCExpr::VK_PREL_G1
)
3787 .Case("prel_g1_nc", AArch64MCExpr::VK_PREL_G1_NC
)
3788 .Case("prel_g0", AArch64MCExpr::VK_PREL_G0
)
3789 .Case("prel_g0_nc", AArch64MCExpr::VK_PREL_G0_NC
)
3790 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2
)
3791 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1
)
3792 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC
)
3793 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0
)
3794 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC
)
3795 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12
)
3796 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12
)
3797 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC
)
3798 .Case("pg_hi21_nc", AArch64MCExpr::VK_ABS_PAGE_NC
)
3799 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2
)
3800 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1
)
3801 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC
)
3802 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0
)
3803 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC
)
3804 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12
)
3805 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12
)
3806 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC
)
3807 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12
)
3808 .Case("got", AArch64MCExpr::VK_GOT_PAGE
)
3809 .Case("gotpage_lo15", AArch64MCExpr::VK_GOT_PAGE_LO15
)
3810 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12
)
3811 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE
)
3812 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC
)
3813 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1
)
3814 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC
)
3815 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE
)
3816 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12
)
3817 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12
)
3818 .Default(AArch64MCExpr::VK_INVALID
);
3820 if (RefKind
== AArch64MCExpr::VK_INVALID
)
3821 return TokError("expect relocation specifier in operand after ':'");
3823 Lex(); // Eat identifier
3825 if (parseToken(AsmToken::Colon
, "expect ':' after relocation specifier"))
3829 if (getParser().parseExpression(ImmVal
))
3833 ImmVal
= AArch64MCExpr::create(ImmVal
, RefKind
, getContext());
3838 OperandMatchResultTy
3839 AArch64AsmParser::tryParseMatrixTileList(OperandVector
&Operands
) {
3840 if (getTok().isNot(AsmToken::LCurly
))
3841 return MatchOperand_NoMatch
;
3843 auto ParseMatrixTile
= [this](unsigned &Reg
, unsigned &ElementWidth
) {
3844 StringRef Name
= getTok().getString();
3845 size_t DotPosition
= Name
.find('.');
3846 if (DotPosition
== StringRef::npos
)
3847 return MatchOperand_NoMatch
;
3849 unsigned RegNum
= matchMatrixTileListRegName(Name
);
3851 return MatchOperand_NoMatch
;
3853 StringRef Tail
= Name
.drop_front(DotPosition
);
3854 const Optional
<std::pair
<int, int>> &KindRes
=
3855 parseVectorKind(Tail
, RegKind::Matrix
);
3857 TokError("Expected the register to be followed by element width suffix");
3858 return MatchOperand_ParseFail
;
3860 ElementWidth
= KindRes
->second
;
3862 Lex(); // Eat the register.
3863 return MatchOperand_Success
;
3867 auto LCurly
= getTok();
3868 Lex(); // Eat left bracket token.
3870 // Empty matrix list
3871 if (parseOptionalToken(AsmToken::RCurly
)) {
3872 Operands
.push_back(AArch64Operand::CreateMatrixTileList(
3873 /*RegMask=*/0, S
, getLoc(), getContext()));
3874 return MatchOperand_Success
;
3877 // Try parse {za} alias early
3878 if (getTok().getString().equals_insensitive("za")) {
3881 if (parseToken(AsmToken::RCurly
, "'}' expected"))
3882 return MatchOperand_ParseFail
;
3884 Operands
.push_back(AArch64Operand::CreateMatrixTileList(
3885 /*RegMask=*/0xFF, S
, getLoc(), getContext()));
3886 return MatchOperand_Success
;
3889 SMLoc TileLoc
= getLoc();
3891 unsigned FirstReg
, ElementWidth
;
3892 auto ParseRes
= ParseMatrixTile(FirstReg
, ElementWidth
);
3893 if (ParseRes
!= MatchOperand_Success
) {
3894 getLexer().UnLex(LCurly
);
3898 const MCRegisterInfo
*RI
= getContext().getRegisterInfo();
3900 unsigned PrevReg
= FirstReg
;
3903 SmallSet
<unsigned, 8> DRegs
;
3904 AArch64Operand::ComputeRegsForAlias(FirstReg
, DRegs
, ElementWidth
);
3906 SmallSet
<unsigned, 8> SeenRegs
;
3907 SeenRegs
.insert(FirstReg
);
3909 while (parseOptionalToken(AsmToken::Comma
)) {
3911 unsigned Reg
, NextElementWidth
;
3912 ParseRes
= ParseMatrixTile(Reg
, NextElementWidth
);
3913 if (ParseRes
!= MatchOperand_Success
)
3916 // Element size must match on all regs in the list.
3917 if (ElementWidth
!= NextElementWidth
) {
3918 Error(TileLoc
, "mismatched register size suffix");
3919 return MatchOperand_ParseFail
;
3922 if (RI
->getEncodingValue(Reg
) <= (RI
->getEncodingValue(PrevReg
)))
3923 Warning(TileLoc
, "tile list not in ascending order");
3925 if (SeenRegs
.contains(Reg
))
3926 Warning(TileLoc
, "duplicate tile in list");
3928 SeenRegs
.insert(Reg
);
3929 AArch64Operand::ComputeRegsForAlias(Reg
, DRegs
, ElementWidth
);
3936 if (parseToken(AsmToken::RCurly
, "'}' expected"))
3937 return MatchOperand_ParseFail
;
3939 unsigned RegMask
= 0;
3940 for (auto Reg
: DRegs
)
3941 RegMask
|= 0x1 << (RI
->getEncodingValue(Reg
) -
3942 RI
->getEncodingValue(AArch64::ZAD0
));
3944 AArch64Operand::CreateMatrixTileList(RegMask
, S
, getLoc(), getContext()));
3946 return MatchOperand_Success
;
3949 template <RegKind VectorKind
>
3950 OperandMatchResultTy
3951 AArch64AsmParser::tryParseVectorList(OperandVector
&Operands
,
3953 MCAsmParser
&Parser
= getParser();
3954 if (!getTok().is(AsmToken::LCurly
))
3955 return MatchOperand_NoMatch
;
3957 // Wrapper around parse function
3958 auto ParseVector
= [this](unsigned &Reg
, StringRef
&Kind
, SMLoc Loc
,
3959 bool NoMatchIsError
) {
3960 auto RegTok
= getTok();
3961 auto ParseRes
= tryParseVectorRegister(Reg
, Kind
, VectorKind
);
3962 if (ParseRes
== MatchOperand_Success
) {
3963 if (parseVectorKind(Kind
, VectorKind
))
3965 llvm_unreachable("Expected a valid vector kind");
3968 if (RegTok
.isNot(AsmToken::Identifier
) ||
3969 ParseRes
== MatchOperand_ParseFail
||
3970 (ParseRes
== MatchOperand_NoMatch
&& NoMatchIsError
&&
3971 !RegTok
.getString().startswith_insensitive("za"))) {
3972 Error(Loc
, "vector register expected");
3973 return MatchOperand_ParseFail
;
3976 return MatchOperand_NoMatch
;
3980 auto LCurly
= getTok();
3981 Lex(); // Eat left bracket token.
3985 auto ParseRes
= ParseVector(FirstReg
, Kind
, getLoc(), ExpectMatch
);
3987 // Put back the original left bracket if there was no match, so that
3988 // different types of list-operands can be matched (e.g. SVE, Neon).
3989 if (ParseRes
== MatchOperand_NoMatch
)
3990 Parser
.getLexer().UnLex(LCurly
);
3992 if (ParseRes
!= MatchOperand_Success
)
3995 int64_t PrevReg
= FirstReg
;
3998 if (parseOptionalToken(AsmToken::Minus
)) {
3999 SMLoc Loc
= getLoc();
4003 ParseRes
= ParseVector(Reg
, NextKind
, getLoc(), true);
4004 if (ParseRes
!= MatchOperand_Success
)
4007 // Any Kind suffices must match on all regs in the list.
4008 if (Kind
!= NextKind
) {
4009 Error(Loc
, "mismatched register size suffix");
4010 return MatchOperand_ParseFail
;
4013 unsigned Space
= (PrevReg
< Reg
) ? (Reg
- PrevReg
) : (Reg
+ 32 - PrevReg
);
4015 if (Space
== 0 || Space
> 3) {
4016 Error(Loc
, "invalid number of vectors");
4017 return MatchOperand_ParseFail
;
4023 while (parseOptionalToken(AsmToken::Comma
)) {
4024 SMLoc Loc
= getLoc();
4027 ParseRes
= ParseVector(Reg
, NextKind
, getLoc(), true);
4028 if (ParseRes
!= MatchOperand_Success
)
4031 // Any Kind suffices must match on all regs in the list.
4032 if (Kind
!= NextKind
) {
4033 Error(Loc
, "mismatched register size suffix");
4034 return MatchOperand_ParseFail
;
4037 // Registers must be incremental (with wraparound at 31)
4038 if (getContext().getRegisterInfo()->getEncodingValue(Reg
) !=
4039 (getContext().getRegisterInfo()->getEncodingValue(PrevReg
) + 1) % 32) {
4040 Error(Loc
, "registers must be sequential");
4041 return MatchOperand_ParseFail
;
4049 if (parseToken(AsmToken::RCurly
, "'}' expected"))
4050 return MatchOperand_ParseFail
;
4053 Error(S
, "invalid number of vectors");
4054 return MatchOperand_ParseFail
;
4057 unsigned NumElements
= 0;
4058 unsigned ElementWidth
= 0;
4059 if (!Kind
.empty()) {
4060 if (const auto &VK
= parseVectorKind(Kind
, VectorKind
))
4061 std::tie(NumElements
, ElementWidth
) = *VK
;
4064 Operands
.push_back(AArch64Operand::CreateVectorList(
4065 FirstReg
, Count
, NumElements
, ElementWidth
, VectorKind
, S
, getLoc(),
4068 return MatchOperand_Success
;
4071 /// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
4072 bool AArch64AsmParser::parseNeonVectorList(OperandVector
&Operands
) {
4073 auto ParseRes
= tryParseVectorList
<RegKind::NeonVector
>(Operands
, true);
4074 if (ParseRes
!= MatchOperand_Success
)
4077 return tryParseVectorIndex(Operands
) == MatchOperand_ParseFail
;
4080 OperandMatchResultTy
4081 AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector
&Operands
) {
4082 SMLoc StartLoc
= getLoc();
4085 OperandMatchResultTy Res
= tryParseScalarRegister(RegNum
);
4086 if (Res
!= MatchOperand_Success
)
4089 if (!parseOptionalToken(AsmToken::Comma
)) {
4090 Operands
.push_back(AArch64Operand::CreateReg(
4091 RegNum
, RegKind::Scalar
, StartLoc
, getLoc(), getContext()));
4092 return MatchOperand_Success
;
4095 parseOptionalToken(AsmToken::Hash
);
4097 if (getTok().isNot(AsmToken::Integer
)) {
4098 Error(getLoc(), "index must be absent or #0");
4099 return MatchOperand_ParseFail
;
4102 const MCExpr
*ImmVal
;
4103 if (getParser().parseExpression(ImmVal
) || !isa
<MCConstantExpr
>(ImmVal
) ||
4104 cast
<MCConstantExpr
>(ImmVal
)->getValue() != 0) {
4105 Error(getLoc(), "index must be absent or #0");
4106 return MatchOperand_ParseFail
;
4109 Operands
.push_back(AArch64Operand::CreateReg(
4110 RegNum
, RegKind::Scalar
, StartLoc
, getLoc(), getContext()));
4111 return MatchOperand_Success
;
4114 template <bool ParseShiftExtend
, RegConstraintEqualityTy EqTy
>
4115 OperandMatchResultTy
4116 AArch64AsmParser::tryParseGPROperand(OperandVector
&Operands
) {
4117 SMLoc StartLoc
= getLoc();
4120 OperandMatchResultTy Res
= tryParseScalarRegister(RegNum
);
4121 if (Res
!= MatchOperand_Success
)
4124 // No shift/extend is the default.
4125 if (!ParseShiftExtend
|| getTok().isNot(AsmToken::Comma
)) {
4126 Operands
.push_back(AArch64Operand::CreateReg(
4127 RegNum
, RegKind::Scalar
, StartLoc
, getLoc(), getContext(), EqTy
));
4128 return MatchOperand_Success
;
4135 SmallVector
<std::unique_ptr
<MCParsedAsmOperand
>, 1> ExtOpnd
;
4136 Res
= tryParseOptionalShiftExtend(ExtOpnd
);
4137 if (Res
!= MatchOperand_Success
)
4140 auto Ext
= static_cast<AArch64Operand
*>(ExtOpnd
.back().get());
4141 Operands
.push_back(AArch64Operand::CreateReg(
4142 RegNum
, RegKind::Scalar
, StartLoc
, Ext
->getEndLoc(), getContext(), EqTy
,
4143 Ext
->getShiftExtendType(), Ext
->getShiftExtendAmount(),
4144 Ext
->hasShiftExtendAmount()));
4146 return MatchOperand_Success
;
4149 bool AArch64AsmParser::parseOptionalMulOperand(OperandVector
&Operands
) {
4150 MCAsmParser
&Parser
= getParser();
4152 // Some SVE instructions have a decoration after the immediate, i.e.
4153 // "mul vl". We parse them here and add tokens, which must be present in the
4154 // asm string in the tablegen instruction.
4156 Parser
.getLexer().peekTok().getString().equals_insensitive("vl");
4157 bool NextIsHash
= Parser
.getLexer().peekTok().is(AsmToken::Hash
);
4158 if (!getTok().getString().equals_insensitive("mul") ||
4159 !(NextIsVL
|| NextIsHash
))
4163 AArch64Operand::CreateToken("mul", getLoc(), getContext()));
4164 Lex(); // Eat the "mul"
4168 AArch64Operand::CreateToken("vl", getLoc(), getContext()));
4169 Lex(); // Eat the "vl"
4177 // Parse immediate operand.
4178 const MCExpr
*ImmVal
;
4179 if (!Parser
.parseExpression(ImmVal
))
4180 if (const MCConstantExpr
*MCE
= dyn_cast
<MCConstantExpr
>(ImmVal
)) {
4181 Operands
.push_back(AArch64Operand::CreateImm(
4182 MCConstantExpr::create(MCE
->getValue(), getContext()), S
, getLoc(),
4184 return MatchOperand_Success
;
4188 return Error(getLoc(), "expected 'vl' or '#<imm>'");
4191 bool AArch64AsmParser::parseKeywordOperand(OperandVector
&Operands
) {
4192 auto Tok
= getTok();
4193 if (Tok
.isNot(AsmToken::Identifier
))
4196 auto Keyword
= Tok
.getString();
4197 Keyword
= StringSwitch
<StringRef
>(Keyword
.lower())
4202 AArch64Operand::CreateToken(Keyword
, Tok
.getLoc(), getContext()));
4208 /// parseOperand - Parse a arm instruction operand. For now this parses the
4209 /// operand regardless of the mnemonic.
4210 bool AArch64AsmParser::parseOperand(OperandVector
&Operands
, bool isCondCode
,
4211 bool invertCondCode
) {
4212 MCAsmParser
&Parser
= getParser();
4214 OperandMatchResultTy ResTy
=
4215 MatchOperandParserImpl(Operands
, Mnemonic
, /*ParseForAllFeatures=*/ true);
4217 // Check if the current operand has a custom associated parser, if so, try to
4218 // custom parse the operand, or fallback to the general approach.
4219 if (ResTy
== MatchOperand_Success
)
4221 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4222 // there was a match, but an error occurred, in which case, just return that
4223 // the operand parsing failed.
4224 if (ResTy
== MatchOperand_ParseFail
)
4227 // Nothing custom, so do general case parsing.
4229 switch (getLexer().getKind()) {
4233 if (parseSymbolicImmVal(Expr
))
4234 return Error(S
, "invalid operand");
4236 SMLoc E
= SMLoc::getFromPointer(getLoc().getPointer() - 1);
4237 Operands
.push_back(AArch64Operand::CreateImm(Expr
, S
, E
, getContext()));
4240 case AsmToken::LBrac
: {
4242 AArch64Operand::CreateToken("[", getLoc(), getContext()));
4245 // There's no comma after a '[', so we can parse the next operand
4247 return parseOperand(Operands
, false, false);
4249 case AsmToken::LCurly
: {
4250 if (!parseNeonVectorList(Operands
))
4254 AArch64Operand::CreateToken("{", getLoc(), getContext()));
4257 // There's no comma after a '{', so we can parse the next operand
4259 return parseOperand(Operands
, false, false);
4261 case AsmToken::Identifier
: {
4262 // If we're expecting a Condition Code operand, then just parse that.
4264 return parseCondCode(Operands
, invertCondCode
);
4266 // If it's a register name, parse it.
4267 if (!parseRegister(Operands
))
4270 // See if this is a "mul vl" decoration or "mul #<int>" operand used
4271 // by SVE instructions.
4272 if (!parseOptionalMulOperand(Operands
))
4275 // If this is an "smstart" or "smstop" instruction, parse its special
4276 // keyword operand as an identifier.
4277 if (Mnemonic
== "smstart" || Mnemonic
== "smstop")
4278 return parseKeywordOperand(Operands
);
4280 // This could be an optional "shift" or "extend" operand.
4281 OperandMatchResultTy GotShift
= tryParseOptionalShiftExtend(Operands
);
4282 // We can only continue if no tokens were eaten.
4283 if (GotShift
!= MatchOperand_NoMatch
)
4286 // If this is a two-word mnemonic, parse its special keyword
4287 // operand as an identifier.
4288 if (Mnemonic
== "brb")
4289 return parseKeywordOperand(Operands
);
4291 // This was not a register so parse other operands that start with an
4292 // identifier (like labels) as expressions and create them as immediates.
4293 const MCExpr
*IdVal
;
4295 if (getParser().parseExpression(IdVal
))
4297 E
= SMLoc::getFromPointer(getLoc().getPointer() - 1);
4298 Operands
.push_back(AArch64Operand::CreateImm(IdVal
, S
, E
, getContext()));
4301 case AsmToken::Integer
:
4302 case AsmToken::Real
:
4303 case AsmToken::Hash
: {
4304 // #42 -> immediate.
4307 parseOptionalToken(AsmToken::Hash
);
4309 // Parse a negative sign
4310 bool isNegative
= false;
4311 if (getTok().is(AsmToken::Minus
)) {
4313 // We need to consume this token only when we have a Real, otherwise
4314 // we let parseSymbolicImmVal take care of it
4315 if (Parser
.getLexer().peekTok().is(AsmToken::Real
))
4319 // The only Real that should come through here is a literal #0.0 for
4320 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
4321 // so convert the value.
4322 const AsmToken
&Tok
= getTok();
4323 if (Tok
.is(AsmToken::Real
)) {
4324 APFloat
RealVal(APFloat::IEEEdouble(), Tok
.getString());
4325 uint64_t IntVal
= RealVal
.bitcastToAPInt().getZExtValue();
4326 if (Mnemonic
!= "fcmp" && Mnemonic
!= "fcmpe" && Mnemonic
!= "fcmeq" &&
4327 Mnemonic
!= "fcmge" && Mnemonic
!= "fcmgt" && Mnemonic
!= "fcmle" &&
4328 Mnemonic
!= "fcmlt" && Mnemonic
!= "fcmne")
4329 return TokError("unexpected floating point literal");
4330 else if (IntVal
!= 0 || isNegative
)
4331 return TokError("expected floating-point constant #0.0");
4332 Lex(); // Eat the token.
4334 Operands
.push_back(AArch64Operand::CreateToken("#0", S
, getContext()));
4335 Operands
.push_back(AArch64Operand::CreateToken(".0", S
, getContext()));
4339 const MCExpr
*ImmVal
;
4340 if (parseSymbolicImmVal(ImmVal
))
4343 E
= SMLoc::getFromPointer(getLoc().getPointer() - 1);
4344 Operands
.push_back(AArch64Operand::CreateImm(ImmVal
, S
, E
, getContext()));
4347 case AsmToken::Equal
: {
4348 SMLoc Loc
= getLoc();
4349 if (Mnemonic
!= "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
4350 return TokError("unexpected token in operand");
4352 const MCExpr
*SubExprVal
;
4353 if (getParser().parseExpression(SubExprVal
))
4356 if (Operands
.size() < 2 ||
4357 !static_cast<AArch64Operand
&>(*Operands
[1]).isScalarReg())
4358 return Error(Loc
, "Only valid when first operand is register");
4361 AArch64MCRegisterClasses
[AArch64::GPR64allRegClassID
].contains(
4362 Operands
[1]->getReg());
4364 MCContext
& Ctx
= getContext();
4365 E
= SMLoc::getFromPointer(Loc
.getPointer() - 1);
4366 // If the op is an imm and can be fit into a mov, then replace ldr with mov.
4367 if (isa
<MCConstantExpr
>(SubExprVal
)) {
4368 uint64_t Imm
= (cast
<MCConstantExpr
>(SubExprVal
))->getValue();
4369 uint32_t ShiftAmt
= 0, MaxShiftAmt
= IsXReg
? 48 : 16;
4370 while(Imm
> 0xFFFF && countTrailingZeros(Imm
) >= 16) {
4374 if (ShiftAmt
<= MaxShiftAmt
&& Imm
<= 0xFFFF) {
4375 Operands
[0] = AArch64Operand::CreateToken("movz", Loc
, Ctx
);
4376 Operands
.push_back(AArch64Operand::CreateImm(
4377 MCConstantExpr::create(Imm
, Ctx
), S
, E
, Ctx
));
4379 Operands
.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL
,
4380 ShiftAmt
, true, S
, E
, Ctx
));
4383 APInt Simm
= APInt(64, Imm
<< ShiftAmt
);
4384 // check if the immediate is an unsigned or signed 32-bit int for W regs
4385 if (!IsXReg
&& !(Simm
.isIntN(32) || Simm
.isSignedIntN(32)))
4386 return Error(Loc
, "Immediate too large for register");
4388 // If it is a label or an imm that cannot fit in a movz, put it into CP.
4389 const MCExpr
*CPLoc
=
4390 getTargetStreamer().addConstantPoolEntry(SubExprVal
, IsXReg
? 8 : 4, Loc
);
4391 Operands
.push_back(AArch64Operand::CreateImm(CPLoc
, S
, E
, Ctx
));
4397 bool AArch64AsmParser::parseImmExpr(int64_t &Out
) {
4398 const MCExpr
*Expr
= nullptr;
4400 if (check(getParser().parseExpression(Expr
), L
, "expected expression"))
4402 const MCConstantExpr
*Value
= dyn_cast_or_null
<MCConstantExpr
>(Expr
);
4403 if (check(!Value
, L
, "expected constant expression"))
4405 Out
= Value
->getValue();
4409 bool AArch64AsmParser::parseComma() {
4410 if (check(getTok().isNot(AsmToken::Comma
), getLoc(), "expected comma"))
4417 bool AArch64AsmParser::parseRegisterInRange(unsigned &Out
, unsigned Base
,
4418 unsigned First
, unsigned Last
) {
4421 if (check(ParseRegister(Reg
, Start
, End
), getLoc(), "expected register"))
4424 // Special handling for FP and LR; they aren't linearly after x28 in
4425 // the registers enum.
4426 unsigned RangeEnd
= Last
;
4427 if (Base
== AArch64::X0
) {
4428 if (Last
== AArch64::FP
) {
4429 RangeEnd
= AArch64::X28
;
4430 if (Reg
== AArch64::FP
) {
4435 if (Last
== AArch64::LR
) {
4436 RangeEnd
= AArch64::X28
;
4437 if (Reg
== AArch64::FP
) {
4440 } else if (Reg
== AArch64::LR
) {
4447 if (check(Reg
< First
|| Reg
> RangeEnd
, Start
,
4448 Twine("expected register in range ") +
4449 AArch64InstPrinter::getRegisterName(First
) + " to " +
4450 AArch64InstPrinter::getRegisterName(Last
)))
4456 bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand
&Op1
,
4457 const MCParsedAsmOperand
&Op2
) const {
4458 auto &AOp1
= static_cast<const AArch64Operand
&>(Op1
);
4459 auto &AOp2
= static_cast<const AArch64Operand
&>(Op2
);
4460 if (AOp1
.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg
&&
4461 AOp2
.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg
)
4462 return MCTargetAsmParser::regsEqual(Op1
, Op2
);
4464 assert(AOp1
.isScalarReg() && AOp2
.isScalarReg() &&
4465 "Testing equality of non-scalar registers not supported");
4467 // Check if a registers match their sub/super register classes.
4468 if (AOp1
.getRegEqualityTy() == EqualsSuperReg
)
4469 return getXRegFromWReg(Op1
.getReg()) == Op2
.getReg();
4470 if (AOp1
.getRegEqualityTy() == EqualsSubReg
)
4471 return getWRegFromXReg(Op1
.getReg()) == Op2
.getReg();
4472 if (AOp2
.getRegEqualityTy() == EqualsSuperReg
)
4473 return getXRegFromWReg(Op2
.getReg()) == Op1
.getReg();
4474 if (AOp2
.getRegEqualityTy() == EqualsSubReg
)
4475 return getWRegFromXReg(Op2
.getReg()) == Op1
.getReg();
4480 /// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
4482 bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo
&Info
,
4483 StringRef Name
, SMLoc NameLoc
,
4484 OperandVector
&Operands
) {
4485 Name
= StringSwitch
<StringRef
>(Name
.lower())
4486 .Case("beq", "b.eq")
4487 .Case("bne", "b.ne")
4488 .Case("bhs", "b.hs")
4489 .Case("bcs", "b.cs")
4490 .Case("blo", "b.lo")
4491 .Case("bcc", "b.cc")
4492 .Case("bmi", "b.mi")
4493 .Case("bpl", "b.pl")
4494 .Case("bvs", "b.vs")
4495 .Case("bvc", "b.vc")
4496 .Case("bhi", "b.hi")
4497 .Case("bls", "b.ls")
4498 .Case("bge", "b.ge")
4499 .Case("blt", "b.lt")
4500 .Case("bgt", "b.gt")
4501 .Case("ble", "b.le")
4502 .Case("bal", "b.al")
4503 .Case("bnv", "b.nv")
4506 // First check for the AArch64-specific .req directive.
4507 if (getTok().is(AsmToken::Identifier
) &&
4508 getTok().getIdentifier().lower() == ".req") {
4509 parseDirectiveReq(Name
, NameLoc
);
4510 // We always return 'error' for this, as we're done with this
4511 // statement and don't need to match the 'instruction."
4515 // Create the leading tokens for the mnemonic, split by '.' characters.
4516 size_t Start
= 0, Next
= Name
.find('.');
4517 StringRef Head
= Name
.slice(Start
, Next
);
4519 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
4520 // the SYS instruction.
4521 if (Head
== "ic" || Head
== "dc" || Head
== "at" || Head
== "tlbi" ||
4522 Head
== "cfp" || Head
== "dvp" || Head
== "cpp")
4523 return parseSysAlias(Head
, NameLoc
, Operands
);
4525 Operands
.push_back(AArch64Operand::CreateToken(Head
, NameLoc
, getContext()));
4528 // Handle condition codes for a branch mnemonic
4529 if (Head
== "b" && Next
!= StringRef::npos
) {
4531 Next
= Name
.find('.', Start
+ 1);
4532 Head
= Name
.slice(Start
+ 1, Next
);
4534 SMLoc SuffixLoc
= SMLoc::getFromPointer(NameLoc
.getPointer() +
4535 (Head
.data() - Name
.data()));
4536 AArch64CC::CondCode CC
= parseCondCodeString(Head
);
4537 if (CC
== AArch64CC::Invalid
)
4538 return Error(SuffixLoc
, "invalid condition code");
4539 Operands
.push_back(AArch64Operand::CreateToken(".", SuffixLoc
, getContext(),
4540 /*IsSuffix=*/true));
4542 AArch64Operand::CreateCondCode(CC
, NameLoc
, NameLoc
, getContext()));
4545 // Add the remaining tokens in the mnemonic.
4546 while (Next
!= StringRef::npos
) {
4548 Next
= Name
.find('.', Start
+ 1);
4549 Head
= Name
.slice(Start
, Next
);
4550 SMLoc SuffixLoc
= SMLoc::getFromPointer(NameLoc
.getPointer() +
4551 (Head
.data() - Name
.data()) + 1);
4552 Operands
.push_back(AArch64Operand::CreateToken(
4553 Head
, SuffixLoc
, getContext(), /*IsSuffix=*/true));
4556 // Conditional compare instructions have a Condition Code operand, which needs
4557 // to be parsed and an immediate operand created.
4558 bool condCodeFourthOperand
=
4559 (Head
== "ccmp" || Head
== "ccmn" || Head
== "fccmp" ||
4560 Head
== "fccmpe" || Head
== "fcsel" || Head
== "csel" ||
4561 Head
== "csinc" || Head
== "csinv" || Head
== "csneg");
4563 // These instructions are aliases to some of the conditional select
4564 // instructions. However, the condition code is inverted in the aliased
4567 // FIXME: Is this the correct way to handle these? Or should the parser
4568 // generate the aliased instructions directly?
4569 bool condCodeSecondOperand
= (Head
== "cset" || Head
== "csetm");
4570 bool condCodeThirdOperand
=
4571 (Head
== "cinc" || Head
== "cinv" || Head
== "cneg");
4573 // Read the remaining operands.
4574 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
4578 // Parse and remember the operand.
4579 if (parseOperand(Operands
, (N
== 4 && condCodeFourthOperand
) ||
4580 (N
== 3 && condCodeThirdOperand
) ||
4581 (N
== 2 && condCodeSecondOperand
),
4582 condCodeSecondOperand
|| condCodeThirdOperand
)) {
4586 // After successfully parsing some operands there are three special cases
4587 // to consider (i.e. notional operands not separated by commas). Two are
4588 // due to memory specifiers:
4589 // + An RBrac will end an address for load/store/prefetch
4590 // + An '!' will indicate a pre-indexed operation.
4592 // And a further case is '}', which ends a group of tokens specifying the
4593 // SME accumulator array 'ZA' or tile vector, i.e.
4595 // '{ ZA }' or '{ <ZAt><HV>.<BHSDQ>[<Wv>, #<imm>] }'
4597 // It's someone else's responsibility to make sure these tokens are sane
4598 // in the given context!
4600 if (parseOptionalToken(AsmToken::RBrac
))
4602 AArch64Operand::CreateToken("]", getLoc(), getContext()));
4603 if (parseOptionalToken(AsmToken::Exclaim
))
4605 AArch64Operand::CreateToken("!", getLoc(), getContext()));
4606 if (parseOptionalToken(AsmToken::RCurly
))
4608 AArch64Operand::CreateToken("}", getLoc(), getContext()));
4611 } while (parseOptionalToken(AsmToken::Comma
));
4614 if (parseToken(AsmToken::EndOfStatement
, "unexpected token in argument list"))
4620 static inline bool isMatchingOrAlias(unsigned ZReg
, unsigned Reg
) {
4621 assert((ZReg
>= AArch64::Z0
) && (ZReg
<= AArch64::Z31
));
4622 return (ZReg
== ((Reg
- AArch64::B0
) + AArch64::Z0
)) ||
4623 (ZReg
== ((Reg
- AArch64::H0
) + AArch64::Z0
)) ||
4624 (ZReg
== ((Reg
- AArch64::S0
) + AArch64::Z0
)) ||
4625 (ZReg
== ((Reg
- AArch64::D0
) + AArch64::Z0
)) ||
4626 (ZReg
== ((Reg
- AArch64::Q0
) + AArch64::Z0
)) ||
4627 (ZReg
== ((Reg
- AArch64::Z0
) + AArch64::Z0
));
4630 // FIXME: This entire function is a giant hack to provide us with decent
4631 // operand range validation/diagnostics until TableGen/MC can be extended
4632 // to support autogeneration of this kind of validation.
4633 bool AArch64AsmParser::validateInstruction(MCInst
&Inst
, SMLoc
&IDLoc
,
4634 SmallVectorImpl
<SMLoc
> &Loc
) {
4635 const MCRegisterInfo
*RI
= getContext().getRegisterInfo();
4636 const MCInstrDesc
&MCID
= MII
.get(Inst
.getOpcode());
4638 // A prefix only applies to the instruction following it. Here we extract
4639 // prefix information for the next instruction before validating the current
4640 // one so that in the case of failure we don't erronously continue using the
4642 PrefixInfo Prefix
= NextPrefix
;
4643 NextPrefix
= PrefixInfo::CreateFromInst(Inst
, MCID
.TSFlags
);
4645 // Before validating the instruction in isolation we run through the rules
4646 // applicable when it follows a prefix instruction.
4647 // NOTE: brk & hlt can be prefixed but require no additional validation.
4648 if (Prefix
.isActive() &&
4649 (Inst
.getOpcode() != AArch64::BRK
) &&
4650 (Inst
.getOpcode() != AArch64::HLT
)) {
4652 // Prefixed intructions must have a destructive operand.
4653 if ((MCID
.TSFlags
& AArch64::DestructiveInstTypeMask
) ==
4654 AArch64::NotDestructive
)
4655 return Error(IDLoc
, "instruction is unpredictable when following a"
4656 " movprfx, suggest replacing movprfx with mov");
4658 // Destination operands must match.
4659 if (Inst
.getOperand(0).getReg() != Prefix
.getDstReg())
4660 return Error(Loc
[0], "instruction is unpredictable when following a"
4661 " movprfx writing to a different destination");
4663 // Destination operand must not be used in any other location.
4664 for (unsigned i
= 1; i
< Inst
.getNumOperands(); ++i
) {
4665 if (Inst
.getOperand(i
).isReg() &&
4666 (MCID
.getOperandConstraint(i
, MCOI::TIED_TO
) == -1) &&
4667 isMatchingOrAlias(Prefix
.getDstReg(), Inst
.getOperand(i
).getReg()))
4668 return Error(Loc
[0], "instruction is unpredictable when following a"
4669 " movprfx and destination also used as non-destructive"
4673 auto PPRRegClass
= AArch64MCRegisterClasses
[AArch64::PPRRegClassID
];
4674 if (Prefix
.isPredicated()) {
4677 // Find the instructions general predicate.
4678 for (unsigned i
= 1; i
< Inst
.getNumOperands(); ++i
)
4679 if (Inst
.getOperand(i
).isReg() &&
4680 PPRRegClass
.contains(Inst
.getOperand(i
).getReg())) {
4685 // Instruction must be predicated if the movprfx is predicated.
4687 (MCID
.TSFlags
& AArch64::ElementSizeMask
) == AArch64::ElementSizeNone
)
4688 return Error(IDLoc
, "instruction is unpredictable when following a"
4689 " predicated movprfx, suggest using unpredicated movprfx");
4691 // Instruction must use same general predicate as the movprfx.
4692 if (Inst
.getOperand(PgIdx
).getReg() != Prefix
.getPgReg())
4693 return Error(IDLoc
, "instruction is unpredictable when following a"
4694 " predicated movprfx using a different general predicate");
4696 // Instruction element type must match the movprfx.
4697 if ((MCID
.TSFlags
& AArch64::ElementSizeMask
) != Prefix
.getElementSize())
4698 return Error(IDLoc
, "instruction is unpredictable when following a"
4699 " predicated movprfx with a different element size");
4703 // Check for indexed addressing modes w/ the base register being the
4704 // same as a destination/source register or pair load where
4705 // the Rt == Rt2. All of those are undefined behaviour.
4706 switch (Inst
.getOpcode()) {
4707 case AArch64::LDPSWpre
:
4708 case AArch64::LDPWpost
:
4709 case AArch64::LDPWpre
:
4710 case AArch64::LDPXpost
:
4711 case AArch64::LDPXpre
: {
4712 unsigned Rt
= Inst
.getOperand(1).getReg();
4713 unsigned Rt2
= Inst
.getOperand(2).getReg();
4714 unsigned Rn
= Inst
.getOperand(3).getReg();
4715 if (RI
->isSubRegisterEq(Rn
, Rt
))
4716 return Error(Loc
[0], "unpredictable LDP instruction, writeback base "
4717 "is also a destination");
4718 if (RI
->isSubRegisterEq(Rn
, Rt2
))
4719 return Error(Loc
[1], "unpredictable LDP instruction, writeback base "
4720 "is also a destination");
4723 case AArch64::LDPDi
:
4724 case AArch64::LDPQi
:
4725 case AArch64::LDPSi
:
4726 case AArch64::LDPSWi
:
4727 case AArch64::LDPWi
:
4728 case AArch64::LDPXi
: {
4729 unsigned Rt
= Inst
.getOperand(0).getReg();
4730 unsigned Rt2
= Inst
.getOperand(1).getReg();
4732 return Error(Loc
[1], "unpredictable LDP instruction, Rt2==Rt");
4735 case AArch64::LDPDpost
:
4736 case AArch64::LDPDpre
:
4737 case AArch64::LDPQpost
:
4738 case AArch64::LDPQpre
:
4739 case AArch64::LDPSpost
:
4740 case AArch64::LDPSpre
:
4741 case AArch64::LDPSWpost
: {
4742 unsigned Rt
= Inst
.getOperand(1).getReg();
4743 unsigned Rt2
= Inst
.getOperand(2).getReg();
4745 return Error(Loc
[1], "unpredictable LDP instruction, Rt2==Rt");
4748 case AArch64::STPDpost
:
4749 case AArch64::STPDpre
:
4750 case AArch64::STPQpost
:
4751 case AArch64::STPQpre
:
4752 case AArch64::STPSpost
:
4753 case AArch64::STPSpre
:
4754 case AArch64::STPWpost
:
4755 case AArch64::STPWpre
:
4756 case AArch64::STPXpost
:
4757 case AArch64::STPXpre
: {
4758 unsigned Rt
= Inst
.getOperand(1).getReg();
4759 unsigned Rt2
= Inst
.getOperand(2).getReg();
4760 unsigned Rn
= Inst
.getOperand(3).getReg();
4761 if (RI
->isSubRegisterEq(Rn
, Rt
))
4762 return Error(Loc
[0], "unpredictable STP instruction, writeback base "
4763 "is also a source");
4764 if (RI
->isSubRegisterEq(Rn
, Rt2
))
4765 return Error(Loc
[1], "unpredictable STP instruction, writeback base "
4766 "is also a source");
4769 case AArch64::LDRBBpre
:
4770 case AArch64::LDRBpre
:
4771 case AArch64::LDRHHpre
:
4772 case AArch64::LDRHpre
:
4773 case AArch64::LDRSBWpre
:
4774 case AArch64::LDRSBXpre
:
4775 case AArch64::LDRSHWpre
:
4776 case AArch64::LDRSHXpre
:
4777 case AArch64::LDRSWpre
:
4778 case AArch64::LDRWpre
:
4779 case AArch64::LDRXpre
:
4780 case AArch64::LDRBBpost
:
4781 case AArch64::LDRBpost
:
4782 case AArch64::LDRHHpost
:
4783 case AArch64::LDRHpost
:
4784 case AArch64::LDRSBWpost
:
4785 case AArch64::LDRSBXpost
:
4786 case AArch64::LDRSHWpost
:
4787 case AArch64::LDRSHXpost
:
4788 case AArch64::LDRSWpost
:
4789 case AArch64::LDRWpost
:
4790 case AArch64::LDRXpost
: {
4791 unsigned Rt
= Inst
.getOperand(1).getReg();
4792 unsigned Rn
= Inst
.getOperand(2).getReg();
4793 if (RI
->isSubRegisterEq(Rn
, Rt
))
4794 return Error(Loc
[0], "unpredictable LDR instruction, writeback base "
4795 "is also a source");
4798 case AArch64::STRBBpost
:
4799 case AArch64::STRBpost
:
4800 case AArch64::STRHHpost
:
4801 case AArch64::STRHpost
:
4802 case AArch64::STRWpost
:
4803 case AArch64::STRXpost
:
4804 case AArch64::STRBBpre
:
4805 case AArch64::STRBpre
:
4806 case AArch64::STRHHpre
:
4807 case AArch64::STRHpre
:
4808 case AArch64::STRWpre
:
4809 case AArch64::STRXpre
: {
4810 unsigned Rt
= Inst
.getOperand(1).getReg();
4811 unsigned Rn
= Inst
.getOperand(2).getReg();
4812 if (RI
->isSubRegisterEq(Rn
, Rt
))
4813 return Error(Loc
[0], "unpredictable STR instruction, writeback base "
4814 "is also a source");
4817 case AArch64::STXRB
:
4818 case AArch64::STXRH
:
4819 case AArch64::STXRW
:
4820 case AArch64::STXRX
:
4821 case AArch64::STLXRB
:
4822 case AArch64::STLXRH
:
4823 case AArch64::STLXRW
:
4824 case AArch64::STLXRX
: {
4825 unsigned Rs
= Inst
.getOperand(0).getReg();
4826 unsigned Rt
= Inst
.getOperand(1).getReg();
4827 unsigned Rn
= Inst
.getOperand(2).getReg();
4828 if (RI
->isSubRegisterEq(Rt
, Rs
) ||
4829 (RI
->isSubRegisterEq(Rn
, Rs
) && Rn
!= AArch64::SP
))
4830 return Error(Loc
[0],
4831 "unpredictable STXR instruction, status is also a source");
4834 case AArch64::STXPW
:
4835 case AArch64::STXPX
:
4836 case AArch64::STLXPW
:
4837 case AArch64::STLXPX
: {
4838 unsigned Rs
= Inst
.getOperand(0).getReg();
4839 unsigned Rt1
= Inst
.getOperand(1).getReg();
4840 unsigned Rt2
= Inst
.getOperand(2).getReg();
4841 unsigned Rn
= Inst
.getOperand(3).getReg();
4842 if (RI
->isSubRegisterEq(Rt1
, Rs
) || RI
->isSubRegisterEq(Rt2
, Rs
) ||
4843 (RI
->isSubRegisterEq(Rn
, Rs
) && Rn
!= AArch64::SP
))
4844 return Error(Loc
[0],
4845 "unpredictable STXP instruction, status is also a source");
4848 case AArch64::LDRABwriteback
:
4849 case AArch64::LDRAAwriteback
: {
4850 unsigned Xt
= Inst
.getOperand(0).getReg();
4851 unsigned Xn
= Inst
.getOperand(1).getReg();
4853 return Error(Loc
[0],
4854 "unpredictable LDRA instruction, writeback base"
4855 " is also a destination");
4861 // Now check immediate ranges. Separate from the above as there is overlap
4862 // in the instructions being checked and this keeps the nested conditionals
4864 switch (Inst
.getOpcode()) {
4865 case AArch64::ADDSWri
:
4866 case AArch64::ADDSXri
:
4867 case AArch64::ADDWri
:
4868 case AArch64::ADDXri
:
4869 case AArch64::SUBSWri
:
4870 case AArch64::SUBSXri
:
4871 case AArch64::SUBWri
:
4872 case AArch64::SUBXri
: {
4873 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4874 // some slight duplication here.
4875 if (Inst
.getOperand(2).isExpr()) {
4876 const MCExpr
*Expr
= Inst
.getOperand(2).getExpr();
4877 AArch64MCExpr::VariantKind ELFRefKind
;
4878 MCSymbolRefExpr::VariantKind DarwinRefKind
;
4880 if (classifySymbolRef(Expr
, ELFRefKind
, DarwinRefKind
, Addend
)) {
4882 // Only allow these with ADDXri.
4883 if ((DarwinRefKind
== MCSymbolRefExpr::VK_PAGEOFF
||
4884 DarwinRefKind
== MCSymbolRefExpr::VK_TLVPPAGEOFF
) &&
4885 Inst
.getOpcode() == AArch64::ADDXri
)
4888 // Only allow these with ADDXri/ADDWri
4889 if ((ELFRefKind
== AArch64MCExpr::VK_LO12
||
4890 ELFRefKind
== AArch64MCExpr::VK_DTPREL_HI12
||
4891 ELFRefKind
== AArch64MCExpr::VK_DTPREL_LO12
||
4892 ELFRefKind
== AArch64MCExpr::VK_DTPREL_LO12_NC
||
4893 ELFRefKind
== AArch64MCExpr::VK_TPREL_HI12
||
4894 ELFRefKind
== AArch64MCExpr::VK_TPREL_LO12
||
4895 ELFRefKind
== AArch64MCExpr::VK_TPREL_LO12_NC
||
4896 ELFRefKind
== AArch64MCExpr::VK_TLSDESC_LO12
||
4897 ELFRefKind
== AArch64MCExpr::VK_SECREL_LO12
||
4898 ELFRefKind
== AArch64MCExpr::VK_SECREL_HI12
) &&
4899 (Inst
.getOpcode() == AArch64::ADDXri
||
4900 Inst
.getOpcode() == AArch64::ADDWri
))
4903 // Don't allow symbol refs in the immediate field otherwise
4904 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4905 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4906 // 'cmp w0, 'borked')
4907 return Error(Loc
.back(), "invalid immediate expression");
4909 // We don't validate more complex expressions here
4918 static std::string
AArch64MnemonicSpellCheck(StringRef S
,
4919 const FeatureBitset
&FBS
,
4920 unsigned VariantID
= 0);
4922 bool AArch64AsmParser::showMatchError(SMLoc Loc
, unsigned ErrCode
,
4924 OperandVector
&Operands
) {
4926 case Match_InvalidTiedOperand
: {
4927 RegConstraintEqualityTy EqTy
=
4928 static_cast<const AArch64Operand
&>(*Operands
[ErrorInfo
])
4929 .getRegEqualityTy();
4931 case RegConstraintEqualityTy::EqualsSubReg
:
4932 return Error(Loc
, "operand must be 64-bit form of destination register");
4933 case RegConstraintEqualityTy::EqualsSuperReg
:
4934 return Error(Loc
, "operand must be 32-bit form of destination register");
4935 case RegConstraintEqualityTy::EqualsReg
:
4936 return Error(Loc
, "operand must match destination register");
4938 llvm_unreachable("Unknown RegConstraintEqualityTy");
4940 case Match_MissingFeature
:
4942 "instruction requires a CPU feature not currently enabled");
4943 case Match_InvalidOperand
:
4944 return Error(Loc
, "invalid operand for instruction");
4945 case Match_InvalidSuffix
:
4946 return Error(Loc
, "invalid type suffix for instruction");
4947 case Match_InvalidCondCode
:
4948 return Error(Loc
, "expected AArch64 condition code");
4949 case Match_AddSubRegExtendSmall
:
4951 "expected '[su]xt[bhw]' with optional integer in range [0, 4]");
4952 case Match_AddSubRegExtendLarge
:
4954 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4955 case Match_AddSubSecondSource
:
4957 "expected compatible register, symbol or integer in range [0, 4095]");
4958 case Match_LogicalSecondSource
:
4959 return Error(Loc
, "expected compatible register or logical immediate");
4960 case Match_InvalidMovImm32Shift
:
4961 return Error(Loc
, "expected 'lsl' with optional integer 0 or 16");
4962 case Match_InvalidMovImm64Shift
:
4963 return Error(Loc
, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4964 case Match_AddSubRegShift32
:
4966 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4967 case Match_AddSubRegShift64
:
4969 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4970 case Match_InvalidFPImm
:
4972 "expected compatible register or floating-point constant");
4973 case Match_InvalidMemoryIndexedSImm6
:
4974 return Error(Loc
, "index must be an integer in range [-32, 31].");
4975 case Match_InvalidMemoryIndexedSImm5
:
4976 return Error(Loc
, "index must be an integer in range [-16, 15].");
4977 case Match_InvalidMemoryIndexed1SImm4
:
4978 return Error(Loc
, "index must be an integer in range [-8, 7].");
4979 case Match_InvalidMemoryIndexed2SImm4
:
4980 return Error(Loc
, "index must be a multiple of 2 in range [-16, 14].");
4981 case Match_InvalidMemoryIndexed3SImm4
:
4982 return Error(Loc
, "index must be a multiple of 3 in range [-24, 21].");
4983 case Match_InvalidMemoryIndexed4SImm4
:
4984 return Error(Loc
, "index must be a multiple of 4 in range [-32, 28].");
4985 case Match_InvalidMemoryIndexed16SImm4
:
4986 return Error(Loc
, "index must be a multiple of 16 in range [-128, 112].");
4987 case Match_InvalidMemoryIndexed32SImm4
:
4988 return Error(Loc
, "index must be a multiple of 32 in range [-256, 224].");
4989 case Match_InvalidMemoryIndexed1SImm6
:
4990 return Error(Loc
, "index must be an integer in range [-32, 31].");
4991 case Match_InvalidMemoryIndexedSImm8
:
4992 return Error(Loc
, "index must be an integer in range [-128, 127].");
4993 case Match_InvalidMemoryIndexedSImm9
:
4994 return Error(Loc
, "index must be an integer in range [-256, 255].");
4995 case Match_InvalidMemoryIndexed16SImm9
:
4996 return Error(Loc
, "index must be a multiple of 16 in range [-4096, 4080].");
4997 case Match_InvalidMemoryIndexed8SImm10
:
4998 return Error(Loc
, "index must be a multiple of 8 in range [-4096, 4088].");
4999 case Match_InvalidMemoryIndexed4SImm7
:
5000 return Error(Loc
, "index must be a multiple of 4 in range [-256, 252].");
5001 case Match_InvalidMemoryIndexed8SImm7
:
5002 return Error(Loc
, "index must be a multiple of 8 in range [-512, 504].");
5003 case Match_InvalidMemoryIndexed16SImm7
:
5004 return Error(Loc
, "index must be a multiple of 16 in range [-1024, 1008].");
5005 case Match_InvalidMemoryIndexed8UImm5
:
5006 return Error(Loc
, "index must be a multiple of 8 in range [0, 248].");
5007 case Match_InvalidMemoryIndexed4UImm5
:
5008 return Error(Loc
, "index must be a multiple of 4 in range [0, 124].");
5009 case Match_InvalidMemoryIndexed2UImm5
:
5010 return Error(Loc
, "index must be a multiple of 2 in range [0, 62].");
5011 case Match_InvalidMemoryIndexed8UImm6
:
5012 return Error(Loc
, "index must be a multiple of 8 in range [0, 504].");
5013 case Match_InvalidMemoryIndexed16UImm6
:
5014 return Error(Loc
, "index must be a multiple of 16 in range [0, 1008].");
5015 case Match_InvalidMemoryIndexed4UImm6
:
5016 return Error(Loc
, "index must be a multiple of 4 in range [0, 252].");
5017 case Match_InvalidMemoryIndexed2UImm6
:
5018 return Error(Loc
, "index must be a multiple of 2 in range [0, 126].");
5019 case Match_InvalidMemoryIndexed1UImm6
:
5020 return Error(Loc
, "index must be in range [0, 63].");
5021 case Match_InvalidMemoryWExtend8
:
5023 "expected 'uxtw' or 'sxtw' with optional shift of #0");
5024 case Match_InvalidMemoryWExtend16
:
5026 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
5027 case Match_InvalidMemoryWExtend32
:
5029 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
5030 case Match_InvalidMemoryWExtend64
:
5032 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
5033 case Match_InvalidMemoryWExtend128
:
5035 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
5036 case Match_InvalidMemoryXExtend8
:
5038 "expected 'lsl' or 'sxtx' with optional shift of #0");
5039 case Match_InvalidMemoryXExtend16
:
5041 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
5042 case Match_InvalidMemoryXExtend32
:
5044 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
5045 case Match_InvalidMemoryXExtend64
:
5047 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
5048 case Match_InvalidMemoryXExtend128
:
5050 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
5051 case Match_InvalidMemoryIndexed1
:
5052 return Error(Loc
, "index must be an integer in range [0, 4095].");
5053 case Match_InvalidMemoryIndexed2
:
5054 return Error(Loc
, "index must be a multiple of 2 in range [0, 8190].");
5055 case Match_InvalidMemoryIndexed4
:
5056 return Error(Loc
, "index must be a multiple of 4 in range [0, 16380].");
5057 case Match_InvalidMemoryIndexed8
:
5058 return Error(Loc
, "index must be a multiple of 8 in range [0, 32760].");
5059 case Match_InvalidMemoryIndexed16
:
5060 return Error(Loc
, "index must be a multiple of 16 in range [0, 65520].");
5061 case Match_InvalidImm0_1
:
5062 return Error(Loc
, "immediate must be an integer in range [0, 1].");
5063 case Match_InvalidImm0_3
:
5064 return Error(Loc
, "immediate must be an integer in range [0, 3].");
5065 case Match_InvalidImm0_7
:
5066 return Error(Loc
, "immediate must be an integer in range [0, 7].");
5067 case Match_InvalidImm0_15
:
5068 return Error(Loc
, "immediate must be an integer in range [0, 15].");
5069 case Match_InvalidImm0_31
:
5070 return Error(Loc
, "immediate must be an integer in range [0, 31].");
5071 case Match_InvalidImm0_63
:
5072 return Error(Loc
, "immediate must be an integer in range [0, 63].");
5073 case Match_InvalidImm0_127
:
5074 return Error(Loc
, "immediate must be an integer in range [0, 127].");
5075 case Match_InvalidImm0_255
:
5076 return Error(Loc
, "immediate must be an integer in range [0, 255].");
5077 case Match_InvalidImm0_65535
:
5078 return Error(Loc
, "immediate must be an integer in range [0, 65535].");
5079 case Match_InvalidImm1_8
:
5080 return Error(Loc
, "immediate must be an integer in range [1, 8].");
5081 case Match_InvalidImm1_16
:
5082 return Error(Loc
, "immediate must be an integer in range [1, 16].");
5083 case Match_InvalidImm1_32
:
5084 return Error(Loc
, "immediate must be an integer in range [1, 32].");
5085 case Match_InvalidImm1_64
:
5086 return Error(Loc
, "immediate must be an integer in range [1, 64].");
5087 case Match_InvalidSVEAddSubImm8
:
5088 return Error(Loc
, "immediate must be an integer in range [0, 255]"
5089 " with a shift amount of 0");
5090 case Match_InvalidSVEAddSubImm16
:
5091 case Match_InvalidSVEAddSubImm32
:
5092 case Match_InvalidSVEAddSubImm64
:
5093 return Error(Loc
, "immediate must be an integer in range [0, 255] or a "
5094 "multiple of 256 in range [256, 65280]");
5095 case Match_InvalidSVECpyImm8
:
5096 return Error(Loc
, "immediate must be an integer in range [-128, 255]"
5097 " with a shift amount of 0");
5098 case Match_InvalidSVECpyImm16
:
5099 return Error(Loc
, "immediate must be an integer in range [-128, 127] or a "
5100 "multiple of 256 in range [-32768, 65280]");
5101 case Match_InvalidSVECpyImm32
:
5102 case Match_InvalidSVECpyImm64
:
5103 return Error(Loc
, "immediate must be an integer in range [-128, 127] or a "
5104 "multiple of 256 in range [-32768, 32512]");
5105 case Match_InvalidIndexRange1_1
:
5106 return Error(Loc
, "expected lane specifier '[1]'");
5107 case Match_InvalidIndexRange0_15
:
5108 return Error(Loc
, "vector lane must be an integer in range [0, 15].");
5109 case Match_InvalidIndexRange0_7
:
5110 return Error(Loc
, "vector lane must be an integer in range [0, 7].");
5111 case Match_InvalidIndexRange0_3
:
5112 return Error(Loc
, "vector lane must be an integer in range [0, 3].");
5113 case Match_InvalidIndexRange0_1
:
5114 return Error(Loc
, "vector lane must be an integer in range [0, 1].");
5115 case Match_InvalidSVEIndexRange0_63
:
5116 return Error(Loc
, "vector lane must be an integer in range [0, 63].");
5117 case Match_InvalidSVEIndexRange0_31
:
5118 return Error(Loc
, "vector lane must be an integer in range [0, 31].");
5119 case Match_InvalidSVEIndexRange0_15
:
5120 return Error(Loc
, "vector lane must be an integer in range [0, 15].");
5121 case Match_InvalidSVEIndexRange0_7
:
5122 return Error(Loc
, "vector lane must be an integer in range [0, 7].");
5123 case Match_InvalidSVEIndexRange0_3
:
5124 return Error(Loc
, "vector lane must be an integer in range [0, 3].");
5125 case Match_InvalidLabel
:
5126 return Error(Loc
, "expected label or encodable integer pc offset");
5128 return Error(Loc
, "expected readable system register");
5130 case Match_InvalidSVCR
:
5131 return Error(Loc
, "expected writable system register or pstate");
5132 case Match_InvalidComplexRotationEven
:
5133 return Error(Loc
, "complex rotation must be 0, 90, 180 or 270.");
5134 case Match_InvalidComplexRotationOdd
:
5135 return Error(Loc
, "complex rotation must be 90 or 270.");
5136 case Match_MnemonicFail
: {
5137 std::string Suggestion
= AArch64MnemonicSpellCheck(
5138 ((AArch64Operand
&)*Operands
[0]).getToken(),
5139 ComputeAvailableFeatures(STI
->getFeatureBits()));
5140 return Error(Loc
, "unrecognized instruction mnemonic" + Suggestion
);
5142 case Match_InvalidGPR64shifted8
:
5143 return Error(Loc
, "register must be x0..x30 or xzr, without shift");
5144 case Match_InvalidGPR64shifted16
:
5145 return Error(Loc
, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
5146 case Match_InvalidGPR64shifted32
:
5147 return Error(Loc
, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
5148 case Match_InvalidGPR64shifted64
:
5149 return Error(Loc
, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
5150 case Match_InvalidGPR64shifted128
:
5152 Loc
, "register must be x0..x30 or xzr, with required shift 'lsl #4'");
5153 case Match_InvalidGPR64NoXZRshifted8
:
5154 return Error(Loc
, "register must be x0..x30 without shift");
5155 case Match_InvalidGPR64NoXZRshifted16
:
5156 return Error(Loc
, "register must be x0..x30 with required shift 'lsl #1'");
5157 case Match_InvalidGPR64NoXZRshifted32
:
5158 return Error(Loc
, "register must be x0..x30 with required shift 'lsl #2'");
5159 case Match_InvalidGPR64NoXZRshifted64
:
5160 return Error(Loc
, "register must be x0..x30 with required shift 'lsl #3'");
5161 case Match_InvalidGPR64NoXZRshifted128
:
5162 return Error(Loc
, "register must be x0..x30 with required shift 'lsl #4'");
5163 case Match_InvalidZPR32UXTW8
:
5164 case Match_InvalidZPR32SXTW8
:
5165 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
5166 case Match_InvalidZPR32UXTW16
:
5167 case Match_InvalidZPR32SXTW16
:
5168 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
5169 case Match_InvalidZPR32UXTW32
:
5170 case Match_InvalidZPR32SXTW32
:
5171 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
5172 case Match_InvalidZPR32UXTW64
:
5173 case Match_InvalidZPR32SXTW64
:
5174 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
5175 case Match_InvalidZPR64UXTW8
:
5176 case Match_InvalidZPR64SXTW8
:
5177 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
5178 case Match_InvalidZPR64UXTW16
:
5179 case Match_InvalidZPR64SXTW16
:
5180 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
5181 case Match_InvalidZPR64UXTW32
:
5182 case Match_InvalidZPR64SXTW32
:
5183 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
5184 case Match_InvalidZPR64UXTW64
:
5185 case Match_InvalidZPR64SXTW64
:
5186 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
5187 case Match_InvalidZPR32LSL8
:
5188 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].s'");
5189 case Match_InvalidZPR32LSL16
:
5190 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
5191 case Match_InvalidZPR32LSL32
:
5192 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
5193 case Match_InvalidZPR32LSL64
:
5194 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
5195 case Match_InvalidZPR64LSL8
:
5196 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].d'");
5197 case Match_InvalidZPR64LSL16
:
5198 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
5199 case Match_InvalidZPR64LSL32
:
5200 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
5201 case Match_InvalidZPR64LSL64
:
5202 return Error(Loc
, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
5203 case Match_InvalidZPR0
:
5204 return Error(Loc
, "expected register without element width suffix");
5205 case Match_InvalidZPR8
:
5206 case Match_InvalidZPR16
:
5207 case Match_InvalidZPR32
:
5208 case Match_InvalidZPR64
:
5209 case Match_InvalidZPR128
:
5210 return Error(Loc
, "invalid element width");
5211 case Match_InvalidZPR_3b8
:
5212 return Error(Loc
, "Invalid restricted vector register, expected z0.b..z7.b");
5213 case Match_InvalidZPR_3b16
:
5214 return Error(Loc
, "Invalid restricted vector register, expected z0.h..z7.h");
5215 case Match_InvalidZPR_3b32
:
5216 return Error(Loc
, "Invalid restricted vector register, expected z0.s..z7.s");
5217 case Match_InvalidZPR_4b16
:
5218 return Error(Loc
, "Invalid restricted vector register, expected z0.h..z15.h");
5219 case Match_InvalidZPR_4b32
:
5220 return Error(Loc
, "Invalid restricted vector register, expected z0.s..z15.s");
5221 case Match_InvalidZPR_4b64
:
5222 return Error(Loc
, "Invalid restricted vector register, expected z0.d..z15.d");
5223 case Match_InvalidSVEPattern
:
5224 return Error(Loc
, "invalid predicate pattern");
5225 case Match_InvalidSVEPredicateAnyReg
:
5226 case Match_InvalidSVEPredicateBReg
:
5227 case Match_InvalidSVEPredicateHReg
:
5228 case Match_InvalidSVEPredicateSReg
:
5229 case Match_InvalidSVEPredicateDReg
:
5230 return Error(Loc
, "invalid predicate register.");
5231 case Match_InvalidSVEPredicate3bAnyReg
:
5232 return Error(Loc
, "invalid restricted predicate register, expected p0..p7 (without element suffix)");
5233 case Match_InvalidSVEExactFPImmOperandHalfOne
:
5234 return Error(Loc
, "Invalid floating point constant, expected 0.5 or 1.0.");
5235 case Match_InvalidSVEExactFPImmOperandHalfTwo
:
5236 return Error(Loc
, "Invalid floating point constant, expected 0.5 or 2.0.");
5237 case Match_InvalidSVEExactFPImmOperandZeroOne
:
5238 return Error(Loc
, "Invalid floating point constant, expected 0.0 or 1.0.");
5239 case Match_InvalidMatrixTileVectorH8
:
5240 case Match_InvalidMatrixTileVectorV8
:
5241 return Error(Loc
, "invalid matrix operand, expected za0h.b or za0v.b");
5242 case Match_InvalidMatrixTileVectorH16
:
5243 case Match_InvalidMatrixTileVectorV16
:
5245 "invalid matrix operand, expected za[0-1]h.h or za[0-1]v.h");
5246 case Match_InvalidMatrixTileVectorH32
:
5247 case Match_InvalidMatrixTileVectorV32
:
5249 "invalid matrix operand, expected za[0-3]h.s or za[0-3]v.s");
5250 case Match_InvalidMatrixTileVectorH64
:
5251 case Match_InvalidMatrixTileVectorV64
:
5253 "invalid matrix operand, expected za[0-7]h.d or za[0-7]v.d");
5254 case Match_InvalidMatrixTileVectorH128
:
5255 case Match_InvalidMatrixTileVectorV128
:
5257 "invalid matrix operand, expected za[0-15]h.q or za[0-15]v.q");
5258 case Match_InvalidMatrixTile32
:
5259 return Error(Loc
, "invalid matrix operand, expected za[0-3].s");
5260 case Match_InvalidMatrixTile64
:
5261 return Error(Loc
, "invalid matrix operand, expected za[0-7].d");
5262 case Match_InvalidMatrix
:
5263 return Error(Loc
, "invalid matrix operand, expected za");
5264 case Match_InvalidMatrixIndexGPR32_12_15
:
5265 return Error(Loc
, "operand must be a register in range [w12, w15]");
5267 llvm_unreachable("unexpected error code!");
5271 static const char *getSubtargetFeatureName(uint64_t Val
);
5273 bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
5274 OperandVector
&Operands
,
5276 uint64_t &ErrorInfo
,
5277 bool MatchingInlineAsm
) {
5278 assert(!Operands
.empty() && "Unexpect empty operand list!");
5279 AArch64Operand
&Op
= static_cast<AArch64Operand
&>(*Operands
[0]);
5280 assert(Op
.isToken() && "Leading operand should always be a mnemonic!");
5282 StringRef Tok
= Op
.getToken();
5283 unsigned NumOperands
= Operands
.size();
5285 if (NumOperands
== 4 && Tok
== "lsl") {
5286 AArch64Operand
&Op2
= static_cast<AArch64Operand
&>(*Operands
[2]);
5287 AArch64Operand
&Op3
= static_cast<AArch64Operand
&>(*Operands
[3]);
5288 if (Op2
.isScalarReg() && Op3
.isImm()) {
5289 const MCConstantExpr
*Op3CE
= dyn_cast
<MCConstantExpr
>(Op3
.getImm());
5291 uint64_t Op3Val
= Op3CE
->getValue();
5292 uint64_t NewOp3Val
= 0;
5293 uint64_t NewOp4Val
= 0;
5294 if (AArch64MCRegisterClasses
[AArch64::GPR32allRegClassID
].contains(
5296 NewOp3Val
= (32 - Op3Val
) & 0x1f;
5297 NewOp4Val
= 31 - Op3Val
;
5299 NewOp3Val
= (64 - Op3Val
) & 0x3f;
5300 NewOp4Val
= 63 - Op3Val
;
5303 const MCExpr
*NewOp3
= MCConstantExpr::create(NewOp3Val
, getContext());
5304 const MCExpr
*NewOp4
= MCConstantExpr::create(NewOp4Val
, getContext());
5307 AArch64Operand::CreateToken("ubfm", Op
.getStartLoc(), getContext());
5308 Operands
.push_back(AArch64Operand::CreateImm(
5309 NewOp4
, Op3
.getStartLoc(), Op3
.getEndLoc(), getContext()));
5310 Operands
[3] = AArch64Operand::CreateImm(NewOp3
, Op3
.getStartLoc(),
5311 Op3
.getEndLoc(), getContext());
5314 } else if (NumOperands
== 4 && Tok
== "bfc") {
5315 // FIXME: Horrible hack to handle BFC->BFM alias.
5316 AArch64Operand
&Op1
= static_cast<AArch64Operand
&>(*Operands
[1]);
5317 AArch64Operand LSBOp
= static_cast<AArch64Operand
&>(*Operands
[2]);
5318 AArch64Operand WidthOp
= static_cast<AArch64Operand
&>(*Operands
[3]);
5320 if (Op1
.isScalarReg() && LSBOp
.isImm() && WidthOp
.isImm()) {
5321 const MCConstantExpr
*LSBCE
= dyn_cast
<MCConstantExpr
>(LSBOp
.getImm());
5322 const MCConstantExpr
*WidthCE
= dyn_cast
<MCConstantExpr
>(WidthOp
.getImm());
5324 if (LSBCE
&& WidthCE
) {
5325 uint64_t LSB
= LSBCE
->getValue();
5326 uint64_t Width
= WidthCE
->getValue();
5328 uint64_t RegWidth
= 0;
5329 if (AArch64MCRegisterClasses
[AArch64::GPR64allRegClassID
].contains(
5335 if (LSB
>= RegWidth
)
5336 return Error(LSBOp
.getStartLoc(),
5337 "expected integer in range [0, 31]");
5338 if (Width
< 1 || Width
> RegWidth
)
5339 return Error(WidthOp
.getStartLoc(),
5340 "expected integer in range [1, 32]");
5344 ImmR
= (32 - LSB
) & 0x1f;
5346 ImmR
= (64 - LSB
) & 0x3f;
5348 uint64_t ImmS
= Width
- 1;
5350 if (ImmR
!= 0 && ImmS
>= ImmR
)
5351 return Error(WidthOp
.getStartLoc(),
5352 "requested insert overflows register");
5354 const MCExpr
*ImmRExpr
= MCConstantExpr::create(ImmR
, getContext());
5355 const MCExpr
*ImmSExpr
= MCConstantExpr::create(ImmS
, getContext());
5357 AArch64Operand::CreateToken("bfm", Op
.getStartLoc(), getContext());
5358 Operands
[2] = AArch64Operand::CreateReg(
5359 RegWidth
== 32 ? AArch64::WZR
: AArch64::XZR
, RegKind::Scalar
,
5360 SMLoc(), SMLoc(), getContext());
5361 Operands
[3] = AArch64Operand::CreateImm(
5362 ImmRExpr
, LSBOp
.getStartLoc(), LSBOp
.getEndLoc(), getContext());
5363 Operands
.emplace_back(
5364 AArch64Operand::CreateImm(ImmSExpr
, WidthOp
.getStartLoc(),
5365 WidthOp
.getEndLoc(), getContext()));
5368 } else if (NumOperands
== 5) {
5369 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
5370 // UBFIZ -> UBFM aliases.
5371 if (Tok
== "bfi" || Tok
== "sbfiz" || Tok
== "ubfiz") {
5372 AArch64Operand
&Op1
= static_cast<AArch64Operand
&>(*Operands
[1]);
5373 AArch64Operand
&Op3
= static_cast<AArch64Operand
&>(*Operands
[3]);
5374 AArch64Operand
&Op4
= static_cast<AArch64Operand
&>(*Operands
[4]);
5376 if (Op1
.isScalarReg() && Op3
.isImm() && Op4
.isImm()) {
5377 const MCConstantExpr
*Op3CE
= dyn_cast
<MCConstantExpr
>(Op3
.getImm());
5378 const MCConstantExpr
*Op4CE
= dyn_cast
<MCConstantExpr
>(Op4
.getImm());
5380 if (Op3CE
&& Op4CE
) {
5381 uint64_t Op3Val
= Op3CE
->getValue();
5382 uint64_t Op4Val
= Op4CE
->getValue();
5384 uint64_t RegWidth
= 0;
5385 if (AArch64MCRegisterClasses
[AArch64::GPR64allRegClassID
].contains(
5391 if (Op3Val
>= RegWidth
)
5392 return Error(Op3
.getStartLoc(),
5393 "expected integer in range [0, 31]");
5394 if (Op4Val
< 1 || Op4Val
> RegWidth
)
5395 return Error(Op4
.getStartLoc(),
5396 "expected integer in range [1, 32]");
5398 uint64_t NewOp3Val
= 0;
5400 NewOp3Val
= (32 - Op3Val
) & 0x1f;
5402 NewOp3Val
= (64 - Op3Val
) & 0x3f;
5404 uint64_t NewOp4Val
= Op4Val
- 1;
5406 if (NewOp3Val
!= 0 && NewOp4Val
>= NewOp3Val
)
5407 return Error(Op4
.getStartLoc(),
5408 "requested insert overflows register");
5410 const MCExpr
*NewOp3
=
5411 MCConstantExpr::create(NewOp3Val
, getContext());
5412 const MCExpr
*NewOp4
=
5413 MCConstantExpr::create(NewOp4Val
, getContext());
5414 Operands
[3] = AArch64Operand::CreateImm(
5415 NewOp3
, Op3
.getStartLoc(), Op3
.getEndLoc(), getContext());
5416 Operands
[4] = AArch64Operand::CreateImm(
5417 NewOp4
, Op4
.getStartLoc(), Op4
.getEndLoc(), getContext());
5419 Operands
[0] = AArch64Operand::CreateToken("bfm", Op
.getStartLoc(),
5421 else if (Tok
== "sbfiz")
5422 Operands
[0] = AArch64Operand::CreateToken("sbfm", Op
.getStartLoc(),
5424 else if (Tok
== "ubfiz")
5425 Operands
[0] = AArch64Operand::CreateToken("ubfm", Op
.getStartLoc(),
5428 llvm_unreachable("No valid mnemonic for alias?");
5432 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
5433 // UBFX -> UBFM aliases.
5434 } else if (NumOperands
== 5 &&
5435 (Tok
== "bfxil" || Tok
== "sbfx" || Tok
== "ubfx")) {
5436 AArch64Operand
&Op1
= static_cast<AArch64Operand
&>(*Operands
[1]);
5437 AArch64Operand
&Op3
= static_cast<AArch64Operand
&>(*Operands
[3]);
5438 AArch64Operand
&Op4
= static_cast<AArch64Operand
&>(*Operands
[4]);
5440 if (Op1
.isScalarReg() && Op3
.isImm() && Op4
.isImm()) {
5441 const MCConstantExpr
*Op3CE
= dyn_cast
<MCConstantExpr
>(Op3
.getImm());
5442 const MCConstantExpr
*Op4CE
= dyn_cast
<MCConstantExpr
>(Op4
.getImm());
5444 if (Op3CE
&& Op4CE
) {
5445 uint64_t Op3Val
= Op3CE
->getValue();
5446 uint64_t Op4Val
= Op4CE
->getValue();
5448 uint64_t RegWidth
= 0;
5449 if (AArch64MCRegisterClasses
[AArch64::GPR64allRegClassID
].contains(
5455 if (Op3Val
>= RegWidth
)
5456 return Error(Op3
.getStartLoc(),
5457 "expected integer in range [0, 31]");
5458 if (Op4Val
< 1 || Op4Val
> RegWidth
)
5459 return Error(Op4
.getStartLoc(),
5460 "expected integer in range [1, 32]");
5462 uint64_t NewOp4Val
= Op3Val
+ Op4Val
- 1;
5464 if (NewOp4Val
>= RegWidth
|| NewOp4Val
< Op3Val
)
5465 return Error(Op4
.getStartLoc(),
5466 "requested extract overflows register");
5468 const MCExpr
*NewOp4
=
5469 MCConstantExpr::create(NewOp4Val
, getContext());
5470 Operands
[4] = AArch64Operand::CreateImm(
5471 NewOp4
, Op4
.getStartLoc(), Op4
.getEndLoc(), getContext());
5473 Operands
[0] = AArch64Operand::CreateToken("bfm", Op
.getStartLoc(),
5475 else if (Tok
== "sbfx")
5476 Operands
[0] = AArch64Operand::CreateToken("sbfm", Op
.getStartLoc(),
5478 else if (Tok
== "ubfx")
5479 Operands
[0] = AArch64Operand::CreateToken("ubfm", Op
.getStartLoc(),
5482 llvm_unreachable("No valid mnemonic for alias?");
5488 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
5489 // instruction for FP registers correctly in some rare circumstances. Convert
5490 // it to a safe instruction and warn (because silently changing someone's
5491 // assembly is rude).
5492 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround
] &&
5493 NumOperands
== 4 && Tok
== "movi") {
5494 AArch64Operand
&Op1
= static_cast<AArch64Operand
&>(*Operands
[1]);
5495 AArch64Operand
&Op2
= static_cast<AArch64Operand
&>(*Operands
[2]);
5496 AArch64Operand
&Op3
= static_cast<AArch64Operand
&>(*Operands
[3]);
5497 if ((Op1
.isToken() && Op2
.isNeonVectorReg() && Op3
.isImm()) ||
5498 (Op1
.isNeonVectorReg() && Op2
.isToken() && Op3
.isImm())) {
5499 StringRef Suffix
= Op1
.isToken() ? Op1
.getToken() : Op2
.getToken();
5500 if (Suffix
.lower() == ".2d" &&
5501 cast
<MCConstantExpr
>(Op3
.getImm())->getValue() == 0) {
5502 Warning(IDLoc
, "instruction movi.2d with immediate #0 may not function"
5503 " correctly on this CPU, converting to equivalent movi.16b");
5504 // Switch the suffix to .16b.
5505 unsigned Idx
= Op1
.isToken() ? 1 : 2;
5507 AArch64Operand::CreateToken(".16b", IDLoc
, getContext());
5512 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
5513 // InstAlias can't quite handle this since the reg classes aren't
5515 if (NumOperands
== 3 && (Tok
== "sxtw" || Tok
== "uxtw")) {
5516 // The source register can be Wn here, but the matcher expects a
5517 // GPR64. Twiddle it here if necessary.
5518 AArch64Operand
&Op
= static_cast<AArch64Operand
&>(*Operands
[2]);
5519 if (Op
.isScalarReg()) {
5520 unsigned Reg
= getXRegFromWReg(Op
.getReg());
5521 Operands
[2] = AArch64Operand::CreateReg(Reg
, RegKind::Scalar
,
5522 Op
.getStartLoc(), Op
.getEndLoc(),
5526 // FIXME: Likewise for sxt[bh] with a Xd dst operand
5527 else if (NumOperands
== 3 && (Tok
== "sxtb" || Tok
== "sxth")) {
5528 AArch64Operand
&Op
= static_cast<AArch64Operand
&>(*Operands
[1]);
5529 if (Op
.isScalarReg() &&
5530 AArch64MCRegisterClasses
[AArch64::GPR64allRegClassID
].contains(
5532 // The source register can be Wn here, but the matcher expects a
5533 // GPR64. Twiddle it here if necessary.
5534 AArch64Operand
&Op
= static_cast<AArch64Operand
&>(*Operands
[2]);
5535 if (Op
.isScalarReg()) {
5536 unsigned Reg
= getXRegFromWReg(Op
.getReg());
5537 Operands
[2] = AArch64Operand::CreateReg(Reg
, RegKind::Scalar
,
5539 Op
.getEndLoc(), getContext());
5543 // FIXME: Likewise for uxt[bh] with a Xd dst operand
5544 else if (NumOperands
== 3 && (Tok
== "uxtb" || Tok
== "uxth")) {
5545 AArch64Operand
&Op
= static_cast<AArch64Operand
&>(*Operands
[1]);
5546 if (Op
.isScalarReg() &&
5547 AArch64MCRegisterClasses
[AArch64::GPR64allRegClassID
].contains(
5549 // The source register can be Wn here, but the matcher expects a
5550 // GPR32. Twiddle it here if necessary.
5551 AArch64Operand
&Op
= static_cast<AArch64Operand
&>(*Operands
[1]);
5552 if (Op
.isScalarReg()) {
5553 unsigned Reg
= getWRegFromXReg(Op
.getReg());
5554 Operands
[1] = AArch64Operand::CreateReg(Reg
, RegKind::Scalar
,
5556 Op
.getEndLoc(), getContext());
5562 FeatureBitset MissingFeatures
;
5563 // First try to match against the secondary set of tables containing the
5564 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
5565 unsigned MatchResult
=
5566 MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MissingFeatures
,
5567 MatchingInlineAsm
, 1);
5569 // If that fails, try against the alternate table containing long-form NEON:
5570 // "fadd v0.2s, v1.2s, v2.2s"
5571 if (MatchResult
!= Match_Success
) {
5572 // But first, save the short-form match result: we can use it in case the
5573 // long-form match also fails.
5574 auto ShortFormNEONErrorInfo
= ErrorInfo
;
5575 auto ShortFormNEONMatchResult
= MatchResult
;
5576 auto ShortFormNEONMissingFeatures
= MissingFeatures
;
5579 MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MissingFeatures
,
5580 MatchingInlineAsm
, 0);
5582 // Now, both matches failed, and the long-form match failed on the mnemonic
5583 // suffix token operand. The short-form match failure is probably more
5584 // relevant: use it instead.
5585 if (MatchResult
== Match_InvalidOperand
&& ErrorInfo
== 1 &&
5586 Operands
.size() > 1 && ((AArch64Operand
&)*Operands
[1]).isToken() &&
5587 ((AArch64Operand
&)*Operands
[1]).isTokenSuffix()) {
5588 MatchResult
= ShortFormNEONMatchResult
;
5589 ErrorInfo
= ShortFormNEONErrorInfo
;
5590 MissingFeatures
= ShortFormNEONMissingFeatures
;
5594 switch (MatchResult
) {
5595 case Match_Success
: {
5596 // Perform range checking and other semantic validations
5597 SmallVector
<SMLoc
, 8> OperandLocs
;
5598 NumOperands
= Operands
.size();
5599 for (unsigned i
= 1; i
< NumOperands
; ++i
)
5600 OperandLocs
.push_back(Operands
[i
]->getStartLoc());
5601 if (validateInstruction(Inst
, IDLoc
, OperandLocs
))
5605 Out
.emitInstruction(Inst
, getSTI());
5608 case Match_MissingFeature
: {
5609 assert(MissingFeatures
.any() && "Unknown missing feature!");
5610 // Special case the error message for the very common case where only
5611 // a single subtarget feature is missing (neon, e.g.).
5612 std::string Msg
= "instruction requires:";
5613 for (unsigned i
= 0, e
= MissingFeatures
.size(); i
!= e
; ++i
) {
5614 if (MissingFeatures
[i
]) {
5616 Msg
+= getSubtargetFeatureName(i
);
5619 return Error(IDLoc
, Msg
);
5621 case Match_MnemonicFail
:
5622 return showMatchError(IDLoc
, MatchResult
, ErrorInfo
, Operands
);
5623 case Match_InvalidOperand
: {
5624 SMLoc ErrorLoc
= IDLoc
;
5626 if (ErrorInfo
!= ~0ULL) {
5627 if (ErrorInfo
>= Operands
.size())
5628 return Error(IDLoc
, "too few operands for instruction",
5629 SMRange(IDLoc
, getTok().getLoc()));
5631 ErrorLoc
= ((AArch64Operand
&)*Operands
[ErrorInfo
]).getStartLoc();
5632 if (ErrorLoc
== SMLoc())
5635 // If the match failed on a suffix token operand, tweak the diagnostic
5637 if (((AArch64Operand
&)*Operands
[ErrorInfo
]).isToken() &&
5638 ((AArch64Operand
&)*Operands
[ErrorInfo
]).isTokenSuffix())
5639 MatchResult
= Match_InvalidSuffix
;
5641 return showMatchError(ErrorLoc
, MatchResult
, ErrorInfo
, Operands
);
5643 case Match_InvalidTiedOperand
:
5644 case Match_InvalidMemoryIndexed1
:
5645 case Match_InvalidMemoryIndexed2
:
5646 case Match_InvalidMemoryIndexed4
:
5647 case Match_InvalidMemoryIndexed8
:
5648 case Match_InvalidMemoryIndexed16
:
5649 case Match_InvalidCondCode
:
5650 case Match_AddSubRegExtendSmall
:
5651 case Match_AddSubRegExtendLarge
:
5652 case Match_AddSubSecondSource
:
5653 case Match_LogicalSecondSource
:
5654 case Match_AddSubRegShift32
:
5655 case Match_AddSubRegShift64
:
5656 case Match_InvalidMovImm32Shift
:
5657 case Match_InvalidMovImm64Shift
:
5658 case Match_InvalidFPImm
:
5659 case Match_InvalidMemoryWExtend8
:
5660 case Match_InvalidMemoryWExtend16
:
5661 case Match_InvalidMemoryWExtend32
:
5662 case Match_InvalidMemoryWExtend64
:
5663 case Match_InvalidMemoryWExtend128
:
5664 case Match_InvalidMemoryXExtend8
:
5665 case Match_InvalidMemoryXExtend16
:
5666 case Match_InvalidMemoryXExtend32
:
5667 case Match_InvalidMemoryXExtend64
:
5668 case Match_InvalidMemoryXExtend128
:
5669 case Match_InvalidMemoryIndexed1SImm4
:
5670 case Match_InvalidMemoryIndexed2SImm4
:
5671 case Match_InvalidMemoryIndexed3SImm4
:
5672 case Match_InvalidMemoryIndexed4SImm4
:
5673 case Match_InvalidMemoryIndexed1SImm6
:
5674 case Match_InvalidMemoryIndexed16SImm4
:
5675 case Match_InvalidMemoryIndexed32SImm4
:
5676 case Match_InvalidMemoryIndexed4SImm7
:
5677 case Match_InvalidMemoryIndexed8SImm7
:
5678 case Match_InvalidMemoryIndexed16SImm7
:
5679 case Match_InvalidMemoryIndexed8UImm5
:
5680 case Match_InvalidMemoryIndexed4UImm5
:
5681 case Match_InvalidMemoryIndexed2UImm5
:
5682 case Match_InvalidMemoryIndexed1UImm6
:
5683 case Match_InvalidMemoryIndexed2UImm6
:
5684 case Match_InvalidMemoryIndexed4UImm6
:
5685 case Match_InvalidMemoryIndexed8UImm6
:
5686 case Match_InvalidMemoryIndexed16UImm6
:
5687 case Match_InvalidMemoryIndexedSImm6
:
5688 case Match_InvalidMemoryIndexedSImm5
:
5689 case Match_InvalidMemoryIndexedSImm8
:
5690 case Match_InvalidMemoryIndexedSImm9
:
5691 case Match_InvalidMemoryIndexed16SImm9
:
5692 case Match_InvalidMemoryIndexed8SImm10
:
5693 case Match_InvalidImm0_1
:
5694 case Match_InvalidImm0_3
:
5695 case Match_InvalidImm0_7
:
5696 case Match_InvalidImm0_15
:
5697 case Match_InvalidImm0_31
:
5698 case Match_InvalidImm0_63
:
5699 case Match_InvalidImm0_127
:
5700 case Match_InvalidImm0_255
:
5701 case Match_InvalidImm0_65535
:
5702 case Match_InvalidImm1_8
:
5703 case Match_InvalidImm1_16
:
5704 case Match_InvalidImm1_32
:
5705 case Match_InvalidImm1_64
:
5706 case Match_InvalidSVEAddSubImm8
:
5707 case Match_InvalidSVEAddSubImm16
:
5708 case Match_InvalidSVEAddSubImm32
:
5709 case Match_InvalidSVEAddSubImm64
:
5710 case Match_InvalidSVECpyImm8
:
5711 case Match_InvalidSVECpyImm16
:
5712 case Match_InvalidSVECpyImm32
:
5713 case Match_InvalidSVECpyImm64
:
5714 case Match_InvalidIndexRange1_1
:
5715 case Match_InvalidIndexRange0_15
:
5716 case Match_InvalidIndexRange0_7
:
5717 case Match_InvalidIndexRange0_3
:
5718 case Match_InvalidIndexRange0_1
:
5719 case Match_InvalidSVEIndexRange0_63
:
5720 case Match_InvalidSVEIndexRange0_31
:
5721 case Match_InvalidSVEIndexRange0_15
:
5722 case Match_InvalidSVEIndexRange0_7
:
5723 case Match_InvalidSVEIndexRange0_3
:
5724 case Match_InvalidLabel
:
5725 case Match_InvalidComplexRotationEven
:
5726 case Match_InvalidComplexRotationOdd
:
5727 case Match_InvalidGPR64shifted8
:
5728 case Match_InvalidGPR64shifted16
:
5729 case Match_InvalidGPR64shifted32
:
5730 case Match_InvalidGPR64shifted64
:
5731 case Match_InvalidGPR64shifted128
:
5732 case Match_InvalidGPR64NoXZRshifted8
:
5733 case Match_InvalidGPR64NoXZRshifted16
:
5734 case Match_InvalidGPR64NoXZRshifted32
:
5735 case Match_InvalidGPR64NoXZRshifted64
:
5736 case Match_InvalidGPR64NoXZRshifted128
:
5737 case Match_InvalidZPR32UXTW8
:
5738 case Match_InvalidZPR32UXTW16
:
5739 case Match_InvalidZPR32UXTW32
:
5740 case Match_InvalidZPR32UXTW64
:
5741 case Match_InvalidZPR32SXTW8
:
5742 case Match_InvalidZPR32SXTW16
:
5743 case Match_InvalidZPR32SXTW32
:
5744 case Match_InvalidZPR32SXTW64
:
5745 case Match_InvalidZPR64UXTW8
:
5746 case Match_InvalidZPR64SXTW8
:
5747 case Match_InvalidZPR64UXTW16
:
5748 case Match_InvalidZPR64SXTW16
:
5749 case Match_InvalidZPR64UXTW32
:
5750 case Match_InvalidZPR64SXTW32
:
5751 case Match_InvalidZPR64UXTW64
:
5752 case Match_InvalidZPR64SXTW64
:
5753 case Match_InvalidZPR32LSL8
:
5754 case Match_InvalidZPR32LSL16
:
5755 case Match_InvalidZPR32LSL32
:
5756 case Match_InvalidZPR32LSL64
:
5757 case Match_InvalidZPR64LSL8
:
5758 case Match_InvalidZPR64LSL16
:
5759 case Match_InvalidZPR64LSL32
:
5760 case Match_InvalidZPR64LSL64
:
5761 case Match_InvalidZPR0
:
5762 case Match_InvalidZPR8
:
5763 case Match_InvalidZPR16
:
5764 case Match_InvalidZPR32
:
5765 case Match_InvalidZPR64
:
5766 case Match_InvalidZPR128
:
5767 case Match_InvalidZPR_3b8
:
5768 case Match_InvalidZPR_3b16
:
5769 case Match_InvalidZPR_3b32
:
5770 case Match_InvalidZPR_4b16
:
5771 case Match_InvalidZPR_4b32
:
5772 case Match_InvalidZPR_4b64
:
5773 case Match_InvalidSVEPredicateAnyReg
:
5774 case Match_InvalidSVEPattern
:
5775 case Match_InvalidSVEPredicateBReg
:
5776 case Match_InvalidSVEPredicateHReg
:
5777 case Match_InvalidSVEPredicateSReg
:
5778 case Match_InvalidSVEPredicateDReg
:
5779 case Match_InvalidSVEPredicate3bAnyReg
:
5780 case Match_InvalidSVEExactFPImmOperandHalfOne
:
5781 case Match_InvalidSVEExactFPImmOperandHalfTwo
:
5782 case Match_InvalidSVEExactFPImmOperandZeroOne
:
5783 case Match_InvalidMatrixTile32
:
5784 case Match_InvalidMatrixTile64
:
5785 case Match_InvalidMatrix
:
5786 case Match_InvalidMatrixTileVectorH8
:
5787 case Match_InvalidMatrixTileVectorH16
:
5788 case Match_InvalidMatrixTileVectorH32
:
5789 case Match_InvalidMatrixTileVectorH64
:
5790 case Match_InvalidMatrixTileVectorH128
:
5791 case Match_InvalidMatrixTileVectorV8
:
5792 case Match_InvalidMatrixTileVectorV16
:
5793 case Match_InvalidMatrixTileVectorV32
:
5794 case Match_InvalidMatrixTileVectorV64
:
5795 case Match_InvalidMatrixTileVectorV128
:
5796 case Match_InvalidSVCR
:
5797 case Match_InvalidMatrixIndexGPR32_12_15
:
5800 if (ErrorInfo
>= Operands
.size())
5801 return Error(IDLoc
, "too few operands for instruction", SMRange(IDLoc
, (*Operands
.back()).getEndLoc()));
5802 // Any time we get here, there's nothing fancy to do. Just get the
5803 // operand SMLoc and display the diagnostic.
5804 SMLoc ErrorLoc
= ((AArch64Operand
&)*Operands
[ErrorInfo
]).getStartLoc();
5805 if (ErrorLoc
== SMLoc())
5807 return showMatchError(ErrorLoc
, MatchResult
, ErrorInfo
, Operands
);
5811 llvm_unreachable("Implement any new match types added!");
5814 /// ParseDirective parses the arm specific directives
5815 bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID
) {
5816 const MCContext::Environment Format
= getContext().getObjectFileType();
5817 bool IsMachO
= Format
== MCContext::IsMachO
;
5818 bool IsCOFF
= Format
== MCContext::IsCOFF
;
5820 auto IDVal
= DirectiveID
.getIdentifier().lower();
5821 SMLoc Loc
= DirectiveID
.getLoc();
5822 if (IDVal
== ".arch")
5823 parseDirectiveArch(Loc
);
5824 else if (IDVal
== ".cpu")
5825 parseDirectiveCPU(Loc
);
5826 else if (IDVal
== ".tlsdesccall")
5827 parseDirectiveTLSDescCall(Loc
);
5828 else if (IDVal
== ".ltorg" || IDVal
== ".pool")
5829 parseDirectiveLtorg(Loc
);
5830 else if (IDVal
== ".unreq")
5831 parseDirectiveUnreq(Loc
);
5832 else if (IDVal
== ".inst")
5833 parseDirectiveInst(Loc
);
5834 else if (IDVal
== ".cfi_negate_ra_state")
5835 parseDirectiveCFINegateRAState();
5836 else if (IDVal
== ".cfi_b_key_frame")
5837 parseDirectiveCFIBKeyFrame();
5838 else if (IDVal
== ".arch_extension")
5839 parseDirectiveArchExtension(Loc
);
5840 else if (IDVal
== ".variant_pcs")
5841 parseDirectiveVariantPCS(Loc
);
5843 if (IDVal
== MCLOHDirectiveName())
5844 parseDirectiveLOH(IDVal
, Loc
);
5847 } else if (IsCOFF
) {
5848 if (IDVal
== ".seh_stackalloc")
5849 parseDirectiveSEHAllocStack(Loc
);
5850 else if (IDVal
== ".seh_endprologue")
5851 parseDirectiveSEHPrologEnd(Loc
);
5852 else if (IDVal
== ".seh_save_r19r20_x")
5853 parseDirectiveSEHSaveR19R20X(Loc
);
5854 else if (IDVal
== ".seh_save_fplr")
5855 parseDirectiveSEHSaveFPLR(Loc
);
5856 else if (IDVal
== ".seh_save_fplr_x")
5857 parseDirectiveSEHSaveFPLRX(Loc
);
5858 else if (IDVal
== ".seh_save_reg")
5859 parseDirectiveSEHSaveReg(Loc
);
5860 else if (IDVal
== ".seh_save_reg_x")
5861 parseDirectiveSEHSaveRegX(Loc
);
5862 else if (IDVal
== ".seh_save_regp")
5863 parseDirectiveSEHSaveRegP(Loc
);
5864 else if (IDVal
== ".seh_save_regp_x")
5865 parseDirectiveSEHSaveRegPX(Loc
);
5866 else if (IDVal
== ".seh_save_lrpair")
5867 parseDirectiveSEHSaveLRPair(Loc
);
5868 else if (IDVal
== ".seh_save_freg")
5869 parseDirectiveSEHSaveFReg(Loc
);
5870 else if (IDVal
== ".seh_save_freg_x")
5871 parseDirectiveSEHSaveFRegX(Loc
);
5872 else if (IDVal
== ".seh_save_fregp")
5873 parseDirectiveSEHSaveFRegP(Loc
);
5874 else if (IDVal
== ".seh_save_fregp_x")
5875 parseDirectiveSEHSaveFRegPX(Loc
);
5876 else if (IDVal
== ".seh_set_fp")
5877 parseDirectiveSEHSetFP(Loc
);
5878 else if (IDVal
== ".seh_add_fp")
5879 parseDirectiveSEHAddFP(Loc
);
5880 else if (IDVal
== ".seh_nop")
5881 parseDirectiveSEHNop(Loc
);
5882 else if (IDVal
== ".seh_save_next")
5883 parseDirectiveSEHSaveNext(Loc
);
5884 else if (IDVal
== ".seh_startepilogue")
5885 parseDirectiveSEHEpilogStart(Loc
);
5886 else if (IDVal
== ".seh_endepilogue")
5887 parseDirectiveSEHEpilogEnd(Loc
);
5888 else if (IDVal
== ".seh_trap_frame")
5889 parseDirectiveSEHTrapFrame(Loc
);
5890 else if (IDVal
== ".seh_pushframe")
5891 parseDirectiveSEHMachineFrame(Loc
);
5892 else if (IDVal
== ".seh_context")
5893 parseDirectiveSEHContext(Loc
);
5894 else if (IDVal
== ".seh_clear_unwound_to_call")
5895 parseDirectiveSEHClearUnwoundToCall(Loc
);
5903 static void ExpandCryptoAEK(AArch64::ArchKind ArchKind
,
5904 SmallVector
<StringRef
, 4> &RequestedExtensions
) {
5905 const bool NoCrypto
= llvm::is_contained(RequestedExtensions
, "nocrypto");
5906 const bool Crypto
= llvm::is_contained(RequestedExtensions
, "crypto");
5908 if (!NoCrypto
&& Crypto
) {
5911 // Map 'generic' (and others) to sha2 and aes, because
5912 // that was the traditional meaning of crypto.
5913 case AArch64::ArchKind::ARMV8_1A
:
5914 case AArch64::ArchKind::ARMV8_2A
:
5915 case AArch64::ArchKind::ARMV8_3A
:
5916 RequestedExtensions
.push_back("sha2");
5917 RequestedExtensions
.push_back("aes");
5919 case AArch64::ArchKind::ARMV8_4A
:
5920 case AArch64::ArchKind::ARMV8_5A
:
5921 case AArch64::ArchKind::ARMV8_6A
:
5922 case AArch64::ArchKind::ARMV8_7A
:
5923 case AArch64::ArchKind::ARMV8R
:
5924 RequestedExtensions
.push_back("sm4");
5925 RequestedExtensions
.push_back("sha3");
5926 RequestedExtensions
.push_back("sha2");
5927 RequestedExtensions
.push_back("aes");
5930 } else if (NoCrypto
) {
5933 // Map 'generic' (and others) to sha2 and aes, because
5934 // that was the traditional meaning of crypto.
5935 case AArch64::ArchKind::ARMV8_1A
:
5936 case AArch64::ArchKind::ARMV8_2A
:
5937 case AArch64::ArchKind::ARMV8_3A
:
5938 RequestedExtensions
.push_back("nosha2");
5939 RequestedExtensions
.push_back("noaes");
5941 case AArch64::ArchKind::ARMV8_4A
:
5942 case AArch64::ArchKind::ARMV8_5A
:
5943 case AArch64::ArchKind::ARMV8_6A
:
5944 case AArch64::ArchKind::ARMV8_7A
:
5945 RequestedExtensions
.push_back("nosm4");
5946 RequestedExtensions
.push_back("nosha3");
5947 RequestedExtensions
.push_back("nosha2");
5948 RequestedExtensions
.push_back("noaes");
5954 /// parseDirectiveArch
5956 bool AArch64AsmParser::parseDirectiveArch(SMLoc L
) {
5957 SMLoc ArchLoc
= getLoc();
5959 StringRef Arch
, ExtensionString
;
5960 std::tie(Arch
, ExtensionString
) =
5961 getParser().parseStringToEndOfStatement().trim().split('+');
5963 AArch64::ArchKind ID
= AArch64::parseArch(Arch
);
5964 if (ID
== AArch64::ArchKind::INVALID
)
5965 return Error(ArchLoc
, "unknown arch name");
5967 if (parseToken(AsmToken::EndOfStatement
))
5970 // Get the architecture and extension features.
5971 std::vector
<StringRef
> AArch64Features
;
5972 AArch64::getArchFeatures(ID
, AArch64Features
);
5973 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID
),
5976 MCSubtargetInfo
&STI
= copySTI();
5977 std::vector
<std::string
> ArchFeatures(AArch64Features
.begin(), AArch64Features
.end());
5978 STI
.setDefaultFeatures("generic", /*TuneCPU*/ "generic",
5979 join(ArchFeatures
.begin(), ArchFeatures
.end(), ","));
5981 SmallVector
<StringRef
, 4> RequestedExtensions
;
5982 if (!ExtensionString
.empty())
5983 ExtensionString
.split(RequestedExtensions
, '+');
5985 ExpandCryptoAEK(ID
, RequestedExtensions
);
5987 FeatureBitset Features
= STI
.getFeatureBits();
5988 for (auto Name
: RequestedExtensions
) {
5989 bool EnableFeature
= true;
5991 if (Name
.startswith_insensitive("no")) {
5992 EnableFeature
= false;
5993 Name
= Name
.substr(2);
5996 for (const auto &Extension
: ExtensionMap
) {
5997 if (Extension
.Name
!= Name
)
6000 if (Extension
.Features
.none())
6001 report_fatal_error("unsupported architectural extension: " + Name
);
6003 FeatureBitset ToggleFeatures
= EnableFeature
6004 ? (~Features
& Extension
.Features
)
6005 : ( Features
& Extension
.Features
);
6006 FeatureBitset Features
=
6007 ComputeAvailableFeatures(STI
.ToggleFeature(ToggleFeatures
));
6008 setAvailableFeatures(Features
);
6015 /// parseDirectiveArchExtension
6016 /// ::= .arch_extension [no]feature
6017 bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L
) {
6018 SMLoc ExtLoc
= getLoc();
6020 StringRef Name
= getParser().parseStringToEndOfStatement().trim();
6022 if (parseToken(AsmToken::EndOfStatement
,
6023 "unexpected token in '.arch_extension' directive"))
6026 bool EnableFeature
= true;
6027 if (Name
.startswith_insensitive("no")) {
6028 EnableFeature
= false;
6029 Name
= Name
.substr(2);
6032 MCSubtargetInfo
&STI
= copySTI();
6033 FeatureBitset Features
= STI
.getFeatureBits();
6034 for (const auto &Extension
: ExtensionMap
) {
6035 if (Extension
.Name
!= Name
)
6038 if (Extension
.Features
.none())
6039 return Error(ExtLoc
, "unsupported architectural extension: " + Name
);
6041 FeatureBitset ToggleFeatures
= EnableFeature
6042 ? (~Features
& Extension
.Features
)
6043 : (Features
& Extension
.Features
);
6044 FeatureBitset Features
=
6045 ComputeAvailableFeatures(STI
.ToggleFeature(ToggleFeatures
));
6046 setAvailableFeatures(Features
);
6050 return Error(ExtLoc
, "unknown architectural extension: " + Name
);
6053 static SMLoc
incrementLoc(SMLoc L
, int Offset
) {
6054 return SMLoc::getFromPointer(L
.getPointer() + Offset
);
6057 /// parseDirectiveCPU
6059 bool AArch64AsmParser::parseDirectiveCPU(SMLoc L
) {
6060 SMLoc CurLoc
= getLoc();
6062 StringRef CPU
, ExtensionString
;
6063 std::tie(CPU
, ExtensionString
) =
6064 getParser().parseStringToEndOfStatement().trim().split('+');
6066 if (parseToken(AsmToken::EndOfStatement
))
6069 SmallVector
<StringRef
, 4> RequestedExtensions
;
6070 if (!ExtensionString
.empty())
6071 ExtensionString
.split(RequestedExtensions
, '+');
6073 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
6074 // once that is tablegen'ed
6075 if (!getSTI().isCPUStringValid(CPU
)) {
6076 Error(CurLoc
, "unknown CPU name");
6080 MCSubtargetInfo
&STI
= copySTI();
6081 STI
.setDefaultFeatures(CPU
, /*TuneCPU*/ CPU
, "");
6082 CurLoc
= incrementLoc(CurLoc
, CPU
.size());
6084 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU
), RequestedExtensions
);
6086 FeatureBitset Features
= STI
.getFeatureBits();
6087 for (auto Name
: RequestedExtensions
) {
6088 // Advance source location past '+'.
6089 CurLoc
= incrementLoc(CurLoc
, 1);
6091 bool EnableFeature
= true;
6093 if (Name
.startswith_insensitive("no")) {
6094 EnableFeature
= false;
6095 Name
= Name
.substr(2);
6098 bool FoundExtension
= false;
6099 for (const auto &Extension
: ExtensionMap
) {
6100 if (Extension
.Name
!= Name
)
6103 if (Extension
.Features
.none())
6104 report_fatal_error("unsupported architectural extension: " + Name
);
6106 FeatureBitset ToggleFeatures
= EnableFeature
6107 ? (~Features
& Extension
.Features
)
6108 : ( Features
& Extension
.Features
);
6109 FeatureBitset Features
=
6110 ComputeAvailableFeatures(STI
.ToggleFeature(ToggleFeatures
));
6111 setAvailableFeatures(Features
);
6112 FoundExtension
= true;
6117 if (!FoundExtension
)
6118 Error(CurLoc
, "unsupported architectural extension");
6120 CurLoc
= incrementLoc(CurLoc
, Name
.size());
6125 /// parseDirectiveInst
6126 /// ::= .inst opcode [, ...]
6127 bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc
) {
6128 if (getLexer().is(AsmToken::EndOfStatement
))
6129 return Error(Loc
, "expected expression following '.inst' directive");
6131 auto parseOp
= [&]() -> bool {
6133 const MCExpr
*Expr
= nullptr;
6134 if (check(getParser().parseExpression(Expr
), L
, "expected expression"))
6136 const MCConstantExpr
*Value
= dyn_cast_or_null
<MCConstantExpr
>(Expr
);
6137 if (check(!Value
, L
, "expected constant expression"))
6139 getTargetStreamer().emitInst(Value
->getValue());
6143 return parseMany(parseOp
);
6146 // parseDirectiveTLSDescCall:
6147 // ::= .tlsdesccall symbol
6148 bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L
) {
6150 if (check(getParser().parseIdentifier(Name
), L
,
6151 "expected symbol after directive") ||
6152 parseToken(AsmToken::EndOfStatement
))
6155 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Name
);
6156 const MCExpr
*Expr
= MCSymbolRefExpr::create(Sym
, getContext());
6157 Expr
= AArch64MCExpr::create(Expr
, AArch64MCExpr::VK_TLSDESC
, getContext());
6160 Inst
.setOpcode(AArch64::TLSDESCCALL
);
6161 Inst
.addOperand(MCOperand::createExpr(Expr
));
6163 getParser().getStreamer().emitInstruction(Inst
, getSTI());
6167 /// ::= .loh <lohName | lohId> label1, ..., labelN
6168 /// The number of arguments depends on the loh identifier.
6169 bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal
, SMLoc Loc
) {
6171 if (getTok().isNot(AsmToken::Identifier
)) {
6172 if (getTok().isNot(AsmToken::Integer
))
6173 return TokError("expected an identifier or a number in directive");
6174 // We successfully get a numeric value for the identifier.
6175 // Check if it is valid.
6176 int64_t Id
= getTok().getIntVal();
6177 if (Id
<= -1U && !isValidMCLOHType(Id
))
6178 return TokError("invalid numeric identifier in directive");
6179 Kind
= (MCLOHType
)Id
;
6181 StringRef Name
= getTok().getIdentifier();
6182 // We successfully parse an identifier.
6183 // Check if it is a recognized one.
6184 int Id
= MCLOHNameToId(Name
);
6187 return TokError("invalid identifier in directive");
6188 Kind
= (MCLOHType
)Id
;
6190 // Consume the identifier.
6192 // Get the number of arguments of this LOH.
6193 int NbArgs
= MCLOHIdToNbArgs(Kind
);
6195 assert(NbArgs
!= -1 && "Invalid number of arguments");
6197 SmallVector
<MCSymbol
*, 3> Args
;
6198 for (int Idx
= 0; Idx
< NbArgs
; ++Idx
) {
6200 if (getParser().parseIdentifier(Name
))
6201 return TokError("expected identifier in directive");
6202 Args
.push_back(getContext().getOrCreateSymbol(Name
));
6204 if (Idx
+ 1 == NbArgs
)
6206 if (parseToken(AsmToken::Comma
,
6207 "unexpected token in '" + Twine(IDVal
) + "' directive"))
6210 if (parseToken(AsmToken::EndOfStatement
,
6211 "unexpected token in '" + Twine(IDVal
) + "' directive"))
6214 getStreamer().emitLOHDirective((MCLOHType
)Kind
, Args
);
6218 /// parseDirectiveLtorg
6219 /// ::= .ltorg | .pool
6220 bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L
) {
6221 if (parseToken(AsmToken::EndOfStatement
, "unexpected token in directive"))
6223 getTargetStreamer().emitCurrentConstantPool();
6227 /// parseDirectiveReq
6228 /// ::= name .req registername
6229 bool AArch64AsmParser::parseDirectiveReq(StringRef Name
, SMLoc L
) {
6230 Lex(); // Eat the '.req' token.
6231 SMLoc SRegLoc
= getLoc();
6232 RegKind RegisterKind
= RegKind::Scalar
;
6234 OperandMatchResultTy ParseRes
= tryParseScalarRegister(RegNum
);
6236 if (ParseRes
!= MatchOperand_Success
) {
6238 RegisterKind
= RegKind::NeonVector
;
6239 ParseRes
= tryParseVectorRegister(RegNum
, Kind
, RegKind::NeonVector
);
6241 if (ParseRes
== MatchOperand_ParseFail
)
6244 if (ParseRes
== MatchOperand_Success
&& !Kind
.empty())
6245 return Error(SRegLoc
, "vector register without type specifier expected");
6248 if (ParseRes
!= MatchOperand_Success
) {
6250 RegisterKind
= RegKind::SVEDataVector
;
6252 tryParseVectorRegister(RegNum
, Kind
, RegKind::SVEDataVector
);
6254 if (ParseRes
== MatchOperand_ParseFail
)
6257 if (ParseRes
== MatchOperand_Success
&& !Kind
.empty())
6258 return Error(SRegLoc
,
6259 "sve vector register without type specifier expected");
6262 if (ParseRes
!= MatchOperand_Success
) {
6264 RegisterKind
= RegKind::SVEPredicateVector
;
6265 ParseRes
= tryParseVectorRegister(RegNum
, Kind
, RegKind::SVEPredicateVector
);
6267 if (ParseRes
== MatchOperand_ParseFail
)
6270 if (ParseRes
== MatchOperand_Success
&& !Kind
.empty())
6271 return Error(SRegLoc
,
6272 "sve predicate register without type specifier expected");
6275 if (ParseRes
!= MatchOperand_Success
)
6276 return Error(SRegLoc
, "register name or alias expected");
6278 // Shouldn't be anything else.
6279 if (parseToken(AsmToken::EndOfStatement
,
6280 "unexpected input in .req directive"))
6283 auto pair
= std::make_pair(RegisterKind
, (unsigned) RegNum
);
6284 if (RegisterReqs
.insert(std::make_pair(Name
, pair
)).first
->second
!= pair
)
6285 Warning(L
, "ignoring redefinition of register alias '" + Name
+ "'");
6290 /// parseDirectiveUneq
6291 /// ::= .unreq registername
6292 bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L
) {
6293 if (getTok().isNot(AsmToken::Identifier
))
6294 return TokError("unexpected input in .unreq directive.");
6295 RegisterReqs
.erase(getTok().getIdentifier().lower());
6296 Lex(); // Eat the identifier.
6297 return parseToken(AsmToken::EndOfStatement
);
6300 bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
6301 if (parseToken(AsmToken::EndOfStatement
, "unexpected token in directive"))
6303 getStreamer().emitCFINegateRAState();
6307 /// parseDirectiveCFIBKeyFrame
6309 bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
6310 if (parseToken(AsmToken::EndOfStatement
,
6311 "unexpected token in '.cfi_b_key_frame'"))
6313 getStreamer().emitCFIBKeyFrame();
6317 /// parseDirectiveVariantPCS
6318 /// ::= .variant_pcs symbolname
6319 bool AArch64AsmParser::parseDirectiveVariantPCS(SMLoc L
) {
6320 const AsmToken
&Tok
= getTok();
6321 if (Tok
.isNot(AsmToken::Identifier
))
6322 return TokError("expected symbol name");
6324 StringRef SymbolName
= Tok
.getIdentifier();
6326 MCSymbol
*Sym
= getContext().lookupSymbol(SymbolName
);
6328 return TokError("unknown symbol");
6330 Lex(); // Eat the symbol
6334 getTargetStreamer().emitDirectiveVariantPCS(Sym
);
6338 /// parseDirectiveSEHAllocStack
6339 /// ::= .seh_stackalloc
6340 bool AArch64AsmParser::parseDirectiveSEHAllocStack(SMLoc L
) {
6342 if (parseImmExpr(Size
))
6344 getTargetStreamer().emitARM64WinCFIAllocStack(Size
);
6348 /// parseDirectiveSEHPrologEnd
6349 /// ::= .seh_endprologue
6350 bool AArch64AsmParser::parseDirectiveSEHPrologEnd(SMLoc L
) {
6351 getTargetStreamer().emitARM64WinCFIPrologEnd();
6355 /// parseDirectiveSEHSaveR19R20X
6356 /// ::= .seh_save_r19r20_x
6357 bool AArch64AsmParser::parseDirectiveSEHSaveR19R20X(SMLoc L
) {
6359 if (parseImmExpr(Offset
))
6361 getTargetStreamer().emitARM64WinCFISaveR19R20X(Offset
);
6365 /// parseDirectiveSEHSaveFPLR
6366 /// ::= .seh_save_fplr
6367 bool AArch64AsmParser::parseDirectiveSEHSaveFPLR(SMLoc L
) {
6369 if (parseImmExpr(Offset
))
6371 getTargetStreamer().emitARM64WinCFISaveFPLR(Offset
);
6375 /// parseDirectiveSEHSaveFPLRX
6376 /// ::= .seh_save_fplr_x
6377 bool AArch64AsmParser::parseDirectiveSEHSaveFPLRX(SMLoc L
) {
6379 if (parseImmExpr(Offset
))
6381 getTargetStreamer().emitARM64WinCFISaveFPLRX(Offset
);
6385 /// parseDirectiveSEHSaveReg
6386 /// ::= .seh_save_reg
6387 bool AArch64AsmParser::parseDirectiveSEHSaveReg(SMLoc L
) {
6390 if (parseRegisterInRange(Reg
, AArch64::X0
, AArch64::X19
, AArch64::LR
) ||
6391 parseComma() || parseImmExpr(Offset
))
6393 getTargetStreamer().emitARM64WinCFISaveReg(Reg
, Offset
);
6397 /// parseDirectiveSEHSaveRegX
6398 /// ::= .seh_save_reg_x
6399 bool AArch64AsmParser::parseDirectiveSEHSaveRegX(SMLoc L
) {
6402 if (parseRegisterInRange(Reg
, AArch64::X0
, AArch64::X19
, AArch64::LR
) ||
6403 parseComma() || parseImmExpr(Offset
))
6405 getTargetStreamer().emitARM64WinCFISaveRegX(Reg
, Offset
);
6409 /// parseDirectiveSEHSaveRegP
6410 /// ::= .seh_save_regp
6411 bool AArch64AsmParser::parseDirectiveSEHSaveRegP(SMLoc L
) {
6414 if (parseRegisterInRange(Reg
, AArch64::X0
, AArch64::X19
, AArch64::FP
) ||
6415 parseComma() || parseImmExpr(Offset
))
6417 getTargetStreamer().emitARM64WinCFISaveRegP(Reg
, Offset
);
6421 /// parseDirectiveSEHSaveRegPX
6422 /// ::= .seh_save_regp_x
6423 bool AArch64AsmParser::parseDirectiveSEHSaveRegPX(SMLoc L
) {
6426 if (parseRegisterInRange(Reg
, AArch64::X0
, AArch64::X19
, AArch64::FP
) ||
6427 parseComma() || parseImmExpr(Offset
))
6429 getTargetStreamer().emitARM64WinCFISaveRegPX(Reg
, Offset
);
6433 /// parseDirectiveSEHSaveLRPair
6434 /// ::= .seh_save_lrpair
6435 bool AArch64AsmParser::parseDirectiveSEHSaveLRPair(SMLoc L
) {
6439 if (parseRegisterInRange(Reg
, AArch64::X0
, AArch64::X19
, AArch64::LR
) ||
6440 parseComma() || parseImmExpr(Offset
))
6442 if (check(((Reg
- 19) % 2 != 0), L
,
6443 "expected register with even offset from x19"))
6445 getTargetStreamer().emitARM64WinCFISaveLRPair(Reg
, Offset
);
6449 /// parseDirectiveSEHSaveFReg
6450 /// ::= .seh_save_freg
6451 bool AArch64AsmParser::parseDirectiveSEHSaveFReg(SMLoc L
) {
6454 if (parseRegisterInRange(Reg
, AArch64::D0
, AArch64::D8
, AArch64::D15
) ||
6455 parseComma() || parseImmExpr(Offset
))
6457 getTargetStreamer().emitARM64WinCFISaveFReg(Reg
, Offset
);
6461 /// parseDirectiveSEHSaveFRegX
6462 /// ::= .seh_save_freg_x
6463 bool AArch64AsmParser::parseDirectiveSEHSaveFRegX(SMLoc L
) {
6466 if (parseRegisterInRange(Reg
, AArch64::D0
, AArch64::D8
, AArch64::D15
) ||
6467 parseComma() || parseImmExpr(Offset
))
6469 getTargetStreamer().emitARM64WinCFISaveFRegX(Reg
, Offset
);
6473 /// parseDirectiveSEHSaveFRegP
6474 /// ::= .seh_save_fregp
6475 bool AArch64AsmParser::parseDirectiveSEHSaveFRegP(SMLoc L
) {
6478 if (parseRegisterInRange(Reg
, AArch64::D0
, AArch64::D8
, AArch64::D14
) ||
6479 parseComma() || parseImmExpr(Offset
))
6481 getTargetStreamer().emitARM64WinCFISaveFRegP(Reg
, Offset
);
6485 /// parseDirectiveSEHSaveFRegPX
6486 /// ::= .seh_save_fregp_x
6487 bool AArch64AsmParser::parseDirectiveSEHSaveFRegPX(SMLoc L
) {
6490 if (parseRegisterInRange(Reg
, AArch64::D0
, AArch64::D8
, AArch64::D14
) ||
6491 parseComma() || parseImmExpr(Offset
))
6493 getTargetStreamer().emitARM64WinCFISaveFRegPX(Reg
, Offset
);
6497 /// parseDirectiveSEHSetFP
6499 bool AArch64AsmParser::parseDirectiveSEHSetFP(SMLoc L
) {
6500 getTargetStreamer().emitARM64WinCFISetFP();
6504 /// parseDirectiveSEHAddFP
6506 bool AArch64AsmParser::parseDirectiveSEHAddFP(SMLoc L
) {
6508 if (parseImmExpr(Size
))
6510 getTargetStreamer().emitARM64WinCFIAddFP(Size
);
6514 /// parseDirectiveSEHNop
6516 bool AArch64AsmParser::parseDirectiveSEHNop(SMLoc L
) {
6517 getTargetStreamer().emitARM64WinCFINop();
6521 /// parseDirectiveSEHSaveNext
6522 /// ::= .seh_save_next
6523 bool AArch64AsmParser::parseDirectiveSEHSaveNext(SMLoc L
) {
6524 getTargetStreamer().emitARM64WinCFISaveNext();
6528 /// parseDirectiveSEHEpilogStart
6529 /// ::= .seh_startepilogue
6530 bool AArch64AsmParser::parseDirectiveSEHEpilogStart(SMLoc L
) {
6531 getTargetStreamer().emitARM64WinCFIEpilogStart();
6535 /// parseDirectiveSEHEpilogEnd
6536 /// ::= .seh_endepilogue
6537 bool AArch64AsmParser::parseDirectiveSEHEpilogEnd(SMLoc L
) {
6538 getTargetStreamer().emitARM64WinCFIEpilogEnd();
6542 /// parseDirectiveSEHTrapFrame
6543 /// ::= .seh_trap_frame
6544 bool AArch64AsmParser::parseDirectiveSEHTrapFrame(SMLoc L
) {
6545 getTargetStreamer().emitARM64WinCFITrapFrame();
6549 /// parseDirectiveSEHMachineFrame
6550 /// ::= .seh_pushframe
6551 bool AArch64AsmParser::parseDirectiveSEHMachineFrame(SMLoc L
) {
6552 getTargetStreamer().emitARM64WinCFIMachineFrame();
6556 /// parseDirectiveSEHContext
6557 /// ::= .seh_context
6558 bool AArch64AsmParser::parseDirectiveSEHContext(SMLoc L
) {
6559 getTargetStreamer().emitARM64WinCFIContext();
6563 /// parseDirectiveSEHClearUnwoundToCall
6564 /// ::= .seh_clear_unwound_to_call
6565 bool AArch64AsmParser::parseDirectiveSEHClearUnwoundToCall(SMLoc L
) {
6566 getTargetStreamer().emitARM64WinCFIClearUnwoundToCall();
6571 AArch64AsmParser::classifySymbolRef(const MCExpr
*Expr
,
6572 AArch64MCExpr::VariantKind
&ELFRefKind
,
6573 MCSymbolRefExpr::VariantKind
&DarwinRefKind
,
6575 ELFRefKind
= AArch64MCExpr::VK_INVALID
;
6576 DarwinRefKind
= MCSymbolRefExpr::VK_None
;
6579 if (const AArch64MCExpr
*AE
= dyn_cast
<AArch64MCExpr
>(Expr
)) {
6580 ELFRefKind
= AE
->getKind();
6581 Expr
= AE
->getSubExpr();
6584 const MCSymbolRefExpr
*SE
= dyn_cast
<MCSymbolRefExpr
>(Expr
);
6586 // It's a simple symbol reference with no addend.
6587 DarwinRefKind
= SE
->getKind();
6591 // Check that it looks like a symbol + an addend
6593 bool Relocatable
= Expr
->evaluateAsRelocatable(Res
, nullptr, nullptr);
6594 if (!Relocatable
|| Res
.getSymB())
6597 // Treat expressions with an ELFRefKind (like ":abs_g1:3", or
6598 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
6599 if (!Res
.getSymA() && ELFRefKind
== AArch64MCExpr::VK_INVALID
)
6603 DarwinRefKind
= Res
.getSymA()->getKind();
6604 Addend
= Res
.getConstant();
6606 // It's some symbol reference + a constant addend, but really
6607 // shouldn't use both Darwin and ELF syntax.
6608 return ELFRefKind
== AArch64MCExpr::VK_INVALID
||
6609 DarwinRefKind
== MCSymbolRefExpr::VK_None
;
6612 /// Force static initialization.
6613 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeAArch64AsmParser() {
6614 RegisterMCAsmParser
<AArch64AsmParser
> X(getTheAArch64leTarget());
6615 RegisterMCAsmParser
<AArch64AsmParser
> Y(getTheAArch64beTarget());
6616 RegisterMCAsmParser
<AArch64AsmParser
> Z(getTheARM64Target());
6617 RegisterMCAsmParser
<AArch64AsmParser
> W(getTheARM64_32Target());
6618 RegisterMCAsmParser
<AArch64AsmParser
> V(getTheAArch64_32Target());
6621 #define GET_REGISTER_MATCHER
6622 #define GET_SUBTARGET_FEATURE_NAME
6623 #define GET_MATCHER_IMPLEMENTATION
6624 #define GET_MNEMONIC_SPELL_CHECKER
6625 #include "AArch64GenAsmMatcher.inc"
6627 // Define this matcher function after the auto-generated include so we
6628 // have the match class enum definitions.
6629 unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand
&AsmOp
,
6631 AArch64Operand
&Op
= static_cast<AArch64Operand
&>(AsmOp
);
6632 // If the kind is a token for a literal immediate, check if our asm
6633 // operand matches. This is for InstAliases which have a fixed-value
6634 // immediate in the syntax.
6635 int64_t ExpectedVal
;
6638 return Match_InvalidOperand
;
6679 // If the Kind is a token for the MPR register class which has the "za"
6680 // register (SME accumulator array), check if the asm is a literal "za"
6681 // token. This is for the "smstart za" alias that defines the register
6682 // as a literal token.
6683 if (Op
.isTokenEqual("za"))
6684 return Match_Success
;
6688 return Match_InvalidOperand
;
6689 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Op
.getImm());
6691 return Match_InvalidOperand
;
6692 if (CE
->getValue() == ExpectedVal
)
6693 return Match_Success
;
6694 return Match_InvalidOperand
;
6697 OperandMatchResultTy
6698 AArch64AsmParser::tryParseGPRSeqPair(OperandVector
&Operands
) {
6702 if (getTok().isNot(AsmToken::Identifier
)) {
6703 Error(S
, "expected register");
6704 return MatchOperand_ParseFail
;
6708 OperandMatchResultTy Res
= tryParseScalarRegister(FirstReg
);
6709 if (Res
!= MatchOperand_Success
)
6710 return MatchOperand_ParseFail
;
6712 const MCRegisterClass
&WRegClass
=
6713 AArch64MCRegisterClasses
[AArch64::GPR32RegClassID
];
6714 const MCRegisterClass
&XRegClass
=
6715 AArch64MCRegisterClasses
[AArch64::GPR64RegClassID
];
6717 bool isXReg
= XRegClass
.contains(FirstReg
),
6718 isWReg
= WRegClass
.contains(FirstReg
);
6719 if (!isXReg
&& !isWReg
) {
6720 Error(S
, "expected first even register of a "
6721 "consecutive same-size even/odd register pair");
6722 return MatchOperand_ParseFail
;
6725 const MCRegisterInfo
*RI
= getContext().getRegisterInfo();
6726 unsigned FirstEncoding
= RI
->getEncodingValue(FirstReg
);
6728 if (FirstEncoding
& 0x1) {
6729 Error(S
, "expected first even register of a "
6730 "consecutive same-size even/odd register pair");
6731 return MatchOperand_ParseFail
;
6734 if (getTok().isNot(AsmToken::Comma
)) {
6735 Error(getLoc(), "expected comma");
6736 return MatchOperand_ParseFail
;
6743 Res
= tryParseScalarRegister(SecondReg
);
6744 if (Res
!= MatchOperand_Success
)
6745 return MatchOperand_ParseFail
;
6747 if (RI
->getEncodingValue(SecondReg
) != FirstEncoding
+ 1 ||
6748 (isXReg
&& !XRegClass
.contains(SecondReg
)) ||
6749 (isWReg
&& !WRegClass
.contains(SecondReg
))) {
6750 Error(E
,"expected second odd register of a "
6751 "consecutive same-size even/odd register pair");
6752 return MatchOperand_ParseFail
;
6757 Pair
= RI
->getMatchingSuperReg(FirstReg
, AArch64::sube64
,
6758 &AArch64MCRegisterClasses
[AArch64::XSeqPairsClassRegClassID
]);
6760 Pair
= RI
->getMatchingSuperReg(FirstReg
, AArch64::sube32
,
6761 &AArch64MCRegisterClasses
[AArch64::WSeqPairsClassRegClassID
]);
6764 Operands
.push_back(AArch64Operand::CreateReg(Pair
, RegKind::Scalar
, S
,
6765 getLoc(), getContext()));
6767 return MatchOperand_Success
;
6770 template <bool ParseShiftExtend
, bool ParseSuffix
>
6771 OperandMatchResultTy
6772 AArch64AsmParser::tryParseSVEDataVector(OperandVector
&Operands
) {
6773 const SMLoc S
= getLoc();
6774 // Check for a SVE vector register specifier first.
6778 OperandMatchResultTy Res
=
6779 tryParseVectorRegister(RegNum
, Kind
, RegKind::SVEDataVector
);
6781 if (Res
!= MatchOperand_Success
)
6784 if (ParseSuffix
&& Kind
.empty())
6785 return MatchOperand_NoMatch
;
6787 const auto &KindRes
= parseVectorKind(Kind
, RegKind::SVEDataVector
);
6789 return MatchOperand_NoMatch
;
6791 unsigned ElementWidth
= KindRes
->second
;
6793 // No shift/extend is the default.
6794 if (!ParseShiftExtend
|| getTok().isNot(AsmToken::Comma
)) {
6795 Operands
.push_back(AArch64Operand::CreateVectorReg(
6796 RegNum
, RegKind::SVEDataVector
, ElementWidth
, S
, S
, getContext()));
6798 OperandMatchResultTy Res
= tryParseVectorIndex(Operands
);
6799 if (Res
== MatchOperand_ParseFail
)
6800 return MatchOperand_ParseFail
;
6801 return MatchOperand_Success
;
6808 SmallVector
<std::unique_ptr
<MCParsedAsmOperand
>, 1> ExtOpnd
;
6809 Res
= tryParseOptionalShiftExtend(ExtOpnd
);
6810 if (Res
!= MatchOperand_Success
)
6813 auto Ext
= static_cast<AArch64Operand
*>(ExtOpnd
.back().get());
6814 Operands
.push_back(AArch64Operand::CreateVectorReg(
6815 RegNum
, RegKind::SVEDataVector
, ElementWidth
, S
, Ext
->getEndLoc(),
6816 getContext(), Ext
->getShiftExtendType(), Ext
->getShiftExtendAmount(),
6817 Ext
->hasShiftExtendAmount()));
6819 return MatchOperand_Success
;
6822 OperandMatchResultTy
6823 AArch64AsmParser::tryParseSVEPattern(OperandVector
&Operands
) {
6824 MCAsmParser
&Parser
= getParser();
6826 SMLoc SS
= getLoc();
6827 const AsmToken
&TokE
= getTok();
6828 bool IsHash
= TokE
.is(AsmToken::Hash
);
6830 if (!IsHash
&& TokE
.isNot(AsmToken::Identifier
))
6831 return MatchOperand_NoMatch
;
6837 // Parse the immediate operand.
6838 const MCExpr
*ImmVal
;
6840 if (Parser
.parseExpression(ImmVal
))
6841 return MatchOperand_ParseFail
;
6843 auto *MCE
= dyn_cast
<MCConstantExpr
>(ImmVal
);
6845 return MatchOperand_ParseFail
;
6847 Pattern
= MCE
->getValue();
6849 // Parse the pattern
6850 auto Pat
= AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE
.getString());
6852 return MatchOperand_NoMatch
;
6855 Pattern
= Pat
->Encoding
;
6856 assert(Pattern
>= 0 && Pattern
< 32);
6860 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern
, getContext()),
6861 SS
, getLoc(), getContext()));
6863 return MatchOperand_Success
;
6866 OperandMatchResultTy
6867 AArch64AsmParser::tryParseGPR64x8(OperandVector
&Operands
) {
6868 SMLoc SS
= getLoc();
6871 if (tryParseScalarRegister(XReg
) != MatchOperand_Success
)
6872 return MatchOperand_NoMatch
;
6874 MCContext
&ctx
= getContext();
6875 const MCRegisterInfo
*RI
= ctx
.getRegisterInfo();
6876 int X8Reg
= RI
->getMatchingSuperReg(
6877 XReg
, AArch64::x8sub_0
,
6878 &AArch64MCRegisterClasses
[AArch64::GPR64x8ClassRegClassID
]);
6880 Error(SS
, "expected an even-numbered x-register in the range [x0,x22]");
6881 return MatchOperand_ParseFail
;
6885 AArch64Operand::CreateReg(X8Reg
, RegKind::Scalar
, SS
, getLoc(), ctx
));
6886 return MatchOperand_Success
;