Coverage Report

Created: 2026-06-08 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/keystone/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Line
Count
Source
1
//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "MCTargetDesc/AArch64AddressingModes.h"
11
#include "MCTargetDesc/AArch64MCExpr.h"
12
#include "MCTargetDesc/AArch64TargetStreamer.h"
13
#include "Utils/AArch64BaseInfo.h"
14
#include "llvm/ADT/APInt.h"
15
#include "llvm/ADT/STLExtras.h"
16
#include "llvm/ADT/SmallString.h"
17
#include "llvm/ADT/SmallVector.h"
18
#include "llvm/ADT/StringSwitch.h"
19
#include "llvm/ADT/Twine.h"
20
#include "llvm/MC/MCContext.h"
21
#include "llvm/MC/MCExpr.h"
22
#include "llvm/MC/MCInst.h"
23
#include "llvm/MC/MCObjectFileInfo.h"
24
#include "llvm/MC/MCParser/MCAsmLexer.h"
25
#include "llvm/MC/MCParser/MCAsmParser.h"
26
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
27
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
28
#include "llvm/MC/MCRegisterInfo.h"
29
#include "llvm/MC/MCStreamer.h"
30
#include "llvm/MC/MCSubtargetInfo.h"
31
#include "llvm/MC/MCSymbol.h"
32
#include "llvm/Support/ErrorHandling.h"
33
#include "llvm/Support/SourceMgr.h"
34
#include "llvm/Support/TargetRegistry.h"
35
#include "llvm/Support/raw_ostream.h"
36
37
#include "keystone/arm64.h"
38
39
#include <cstdio>
40
using namespace llvm_ks;
41
42
namespace {
43
44
class AArch64Operand;
45
46
class AArch64AsmParser : public MCTargetAsmParser {
47
private:
48
  StringRef Mnemonic; ///< Instruction mnemonic.
49
50
  // Map of register aliases registers via the .req directive.
51
  StringMap<std::pair<bool, unsigned> > RegisterReqs;
52
53
542
  AArch64TargetStreamer &getTargetStreamer() {
54
542
    MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
55
542
    return static_cast<AArch64TargetStreamer &>(TS);
56
542
  }
57
58
113k
  SMLoc getLoc() const { return getParser().getTok().getLoc(); }
59
60
  bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
61
  AArch64CC::CondCode parseCondCodeString(StringRef Cond);
62
  bool parseCondCode(OperandVector &Operands, bool invertCondCode);
63
  unsigned matchRegisterNameAlias(StringRef Name, bool isVector);
64
  int tryParseRegister();
65
  int tryMatchVectorRegister(StringRef &Kind, bool expected);
66
  bool parseRegister(OperandVector &Operands);
67
  bool parseSymbolicImmVal(const MCExpr *&ImmVal);
68
  bool parseVectorList(OperandVector &Operands);
69
  bool parseOperand(OperandVector &Operands, bool isCondCode,
70
                    bool invertCondCode);
71
72
0
  void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); }
73
  //bool Error(SMLoc L, const Twine &Msg) { return getParser().Error(L, Msg); }
74
  //bool Error(SMLoc L, const Twine &Msg) { return true; }
75
  bool showMatchError(SMLoc Loc, unsigned ErrCode);
76
77
  bool parseDirectiveWord(unsigned Size, SMLoc L);
78
  bool parseDirectiveInst(SMLoc L);
79
80
  bool parseDirectiveTLSDescCall(SMLoc L);
81
82
  bool parseDirectiveLOH(StringRef LOH, SMLoc L);
83
  bool parseDirectiveLtorg(SMLoc L);
84
85
  bool parseDirectiveReq(StringRef Name, SMLoc L);
86
  bool parseDirectiveUnreq(SMLoc L);
87
88
  bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
89
  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
90
                               OperandVector &Operands, MCStreamer &Out,
91
                               uint64_t &ErrorInfo,
92
                               bool MatchingInlineAsm, unsigned int &ErrorCode, uint64_t &Address) override;
93
/// @name Auto-generated Match Functions
94
/// {
95
96
#define GET_ASSEMBLER_HEADER
97
#include "AArch64GenAsmMatcher.inc"
98
99
  /// }
100
101
  OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
102
  OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
103
  OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
104
  OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
105
  OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
106
  OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
107
  OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
108
  OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
109
  OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
110
  OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
111
  OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
112
  OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
113
  bool tryParseVectorRegister(OperandVector &Operands);
114
  OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
115
116
public:
117
  enum AArch64MatchResultTy {
118
    Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
119
#define GET_OPERAND_DIAGNOSTIC_TYPES
120
#include "AArch64GenAsmMatcher.inc"
121
  };
122
  AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
123
                   const MCInstrInfo &MII, const MCTargetOptions &Options)
124
2.00k
    : MCTargetAsmParser(Options, STI) {
125
2.00k
    MCAsmParserExtension::Initialize(Parser);
126
2.00k
    MCStreamer &S = getParser().getStreamer();
127
2.00k
    if (S.getTargetStreamer() == nullptr)
128
2.00k
      new AArch64TargetStreamer(S);
129
130
    // Initialize the set of available features.
131
2.00k
    setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
132
2.00k
  }
133
134
  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
135
                        SMLoc NameLoc, OperandVector &Operands, unsigned int &ErrorCode) override;
136
  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, unsigned int &ErrorCode) override;
137
  bool ParseDirective(AsmToken DirectiveID) override;
138
  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
139
                                      unsigned Kind) override;
140
141
  static bool classifySymbolRef(const MCExpr *Expr,
142
                                AArch64MCExpr::VariantKind &ELFRefKind,
143
                                MCSymbolRefExpr::VariantKind &DarwinRefKind,
144
                                int64_t &Addend);
145
};
146
} // end anonymous namespace
147
148
namespace {
149
150
/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
151
/// instruction.
152
class AArch64Operand : public MCParsedAsmOperand {
153
private:
154
  enum KindTy {
155
    k_Immediate,
156
    k_ShiftedImm,
157
    k_CondCode,
158
    k_Register,
159
    k_VectorList,
160
    k_VectorIndex,
161
    k_Token,
162
    k_SysReg,
163
    k_SysCR,
164
    k_Prefetch,
165
    k_ShiftExtend,
166
    k_FPImm,
167
    k_Barrier,
168
    k_PSBHint,
169
  } Kind;
170
171
  SMLoc StartLoc, EndLoc;
172
173
  struct TokOp {
174
    const char *Data;
175
    unsigned Length;
176
    bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
177
  };
178
179
  struct RegOp {
180
    unsigned RegNum;
181
    bool isVector;
182
  };
183
184
  struct VectorListOp {
185
    unsigned RegNum;
186
    unsigned Count;
187
    unsigned NumElements;
188
    unsigned ElementKind;
189
  };
190
191
  struct VectorIndexOp {
192
    unsigned Val;
193
  };
194
195
  struct ImmOp {
196
    const MCExpr *Val;
197
  };
198
199
  struct ShiftedImmOp {
200
    const MCExpr *Val;
201
    unsigned ShiftAmount;
202
  };
203
204
  struct CondCodeOp {
205
    AArch64CC::CondCode Code;
206
  };
207
208
  struct FPImmOp {
209
    unsigned Val; // Encoded 8-bit representation.
210
  };
211
212
  struct BarrierOp {
213
    unsigned Val; // Not the enum since not all values have names.
214
    const char *Data;
215
    unsigned Length;
216
  };
217
218
  struct SysRegOp {
219
    const char *Data;
220
    unsigned Length;
221
    uint32_t MRSReg;
222
    uint32_t MSRReg;
223
    uint32_t PStateField;
224
  };
225
226
  struct SysCRImmOp {
227
    unsigned Val;
228
  };
229
230
  struct PrefetchOp {
231
    unsigned Val;
232
    const char *Data;
233
    unsigned Length;
234
  };
235
236
  struct PSBHintOp {
237
    unsigned Val;
238
    const char *Data;
239
    unsigned Length;
240
  };
241
242
  struct ShiftExtendOp {
243
    AArch64_AM::ShiftExtendType Type;
244
    unsigned Amount;
245
    bool HasExplicitAmount;
246
  };
247
248
  struct ExtendOp {
249
    unsigned Val;
250
  };
251
252
  union {
253
    struct TokOp Tok;
254
    struct RegOp Reg;
255
    struct VectorListOp VectorList;
256
    struct VectorIndexOp VectorIndex;
257
    struct ImmOp Imm;
258
    struct ShiftedImmOp ShiftedImm;
259
    struct CondCodeOp CondCode;
260
    struct FPImmOp FPImm;
261
    struct BarrierOp Barrier;
262
    struct SysRegOp SysReg;
263
    struct SysCRImmOp SysCRImm;
264
    struct PrefetchOp Prefetch;
265
    struct PSBHintOp PSBHint;
266
    struct ShiftExtendOp ShiftExtend;
267
  };
268
269
  // Keep the MCContext around as the MCExprs may need manipulated during
270
  // the add<>Operands() calls.
271
  MCContext &Ctx;
272
273
public:
274
125k
  AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
275
276
0
  AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
277
0
    Kind = o.Kind;
278
0
    StartLoc = o.StartLoc;
279
0
    EndLoc = o.EndLoc;
280
0
    switch (Kind) {
281
0
    case k_Token:
282
0
      Tok = o.Tok;
283
0
      break;
284
0
    case k_Immediate:
285
0
      Imm = o.Imm;
286
0
      break;
287
0
    case k_ShiftedImm:
288
0
      ShiftedImm = o.ShiftedImm;
289
0
      break;
290
0
    case k_CondCode:
291
0
      CondCode = o.CondCode;
292
0
      break;
293
0
    case k_FPImm:
294
0
      FPImm = o.FPImm;
295
0
      break;
296
0
    case k_Barrier:
297
0
      Barrier = o.Barrier;
298
0
      break;
299
0
    case k_Register:
300
0
      Reg = o.Reg;
301
0
      break;
302
0
    case k_VectorList:
303
0
      VectorList = o.VectorList;
304
0
      break;
305
0
    case k_VectorIndex:
306
0
      VectorIndex = o.VectorIndex;
307
0
      break;
308
0
    case k_SysReg:
309
0
      SysReg = o.SysReg;
310
0
      break;
311
0
    case k_SysCR:
312
0
      SysCRImm = o.SysCRImm;
313
0
      break;
314
0
    case k_Prefetch:
315
0
      Prefetch = o.Prefetch;
316
0
      break;
317
0
    case k_PSBHint:
318
0
      PSBHint = o.PSBHint;
319
0
      break;
320
0
    case k_ShiftExtend:
321
0
      ShiftExtend = o.ShiftExtend;
322
0
      break;
323
0
    }
324
0
  }
325
326
  /// getStartLoc - Get the location of the first token of this operand.
327
3.08k
  SMLoc getStartLoc() const override { return StartLoc; }
328
  /// getEndLoc - Get the location of the last token of this operand.
329
1
  SMLoc getEndLoc() const override { return EndLoc; }
330
331
6.33k
  StringRef getToken() const {
332
6.33k
    assert(Kind == k_Token && "Invalid access!");
333
6.33k
    return StringRef(Tok.Data, Tok.Length);
334
6.33k
  }
335
336
22
  bool isTokenSuffix() const {
337
22
    assert(Kind == k_Token && "Invalid access!");
338
22
    return Tok.IsSuffix;
339
22
  }
340
341
4.48k
  const MCExpr *getImm() const {
342
4.48k
    assert(Kind == k_Immediate && "Invalid access!");
343
4.48k
    return Imm.Val;
344
4.48k
  }
345
346
11
  const MCExpr *getShiftedImmVal() const {
347
11
    assert(Kind == k_ShiftedImm && "Invalid access!");
348
11
    return ShiftedImm.Val;
349
11
  }
350
351
7
  unsigned getShiftedImmShift() const {
352
7
    assert(Kind == k_ShiftedImm && "Invalid access!");
353
7
    return ShiftedImm.ShiftAmount;
354
7
  }
355
356
389
  AArch64CC::CondCode getCondCode() const {
357
389
    assert(Kind == k_CondCode && "Invalid access!");
358
389
    return CondCode.Code;
359
389
  }
360
361
1
  unsigned getFPImm() const {
362
1
    assert(Kind == k_FPImm && "Invalid access!");
363
1
    return FPImm.Val;
364
1
  }
365
366
50
  unsigned getBarrier() const {
367
50
    assert(Kind == k_Barrier && "Invalid access!");
368
50
    return Barrier.Val;
369
50
  }
370
371
0
  StringRef getBarrierName() const {
372
0
    assert(Kind == k_Barrier && "Invalid access!");
373
0
    return StringRef(Barrier.Data, Barrier.Length);
374
0
  }
375
376
2.83k
  unsigned getReg() const override {
377
2.83k
    assert(Kind == k_Register && "Invalid access!");
378
2.83k
    return Reg.RegNum;
379
2.83k
  }
380
381
0
  unsigned getVectorListStart() const {
382
0
    assert(Kind == k_VectorList && "Invalid access!");
383
0
    return VectorList.RegNum;
384
0
  }
385
386
0
  unsigned getVectorListCount() const {
387
0
    assert(Kind == k_VectorList && "Invalid access!");
388
0
    return VectorList.Count;
389
0
  }
390
391
0
  unsigned getVectorIndex() const {
392
0
    assert(Kind == k_VectorIndex && "Invalid access!");
393
0
    return VectorIndex.Val;
394
0
  }
395
396
0
  StringRef getSysReg() const {
397
0
    assert(Kind == k_SysReg && "Invalid access!");
398
0
    return StringRef(SysReg.Data, SysReg.Length);
399
0
  }
400
401
0
  unsigned getSysCR() const {
402
0
    assert(Kind == k_SysCR && "Invalid access!");
403
0
    return SysCRImm.Val;
404
0
  }
405
406
0
  unsigned getPrefetch() const {
407
0
    assert(Kind == k_Prefetch && "Invalid access!");
408
0
    return Prefetch.Val;
409
0
  }
410
411
0
  unsigned getPSBHint() const {
412
0
    assert(Kind == k_PSBHint && "Invalid access!");
413
0
    return PSBHint.Val;
414
0
  }
415
416
0
  StringRef getPSBHintName() const {
417
0
    assert(Kind == k_PSBHint && "Invalid access!");
418
0
    return StringRef(PSBHint.Data, PSBHint.Length);
419
0
  }
420
421
0
  StringRef getPrefetchName() const {
422
0
    assert(Kind == k_Prefetch && "Invalid access!");
423
0
    return StringRef(Prefetch.Data, Prefetch.Length);
424
0
  }
425
426
3
  AArch64_AM::ShiftExtendType getShiftExtendType() const {
427
3
    assert(Kind == k_ShiftExtend && "Invalid access!");
428
3
    return ShiftExtend.Type;
429
3
  }
430
431
2
  unsigned getShiftExtendAmount() const {
432
2
    assert(Kind == k_ShiftExtend && "Invalid access!");
433
2
    return ShiftExtend.Amount;
434
2
  }
435
436
0
  bool hasShiftExtendAmount() const {
437
0
    assert(Kind == k_ShiftExtend && "Invalid access!");
438
0
    return ShiftExtend.HasExplicitAmount;
439
0
  }
440
441
1.52k
  bool isImm() const override { return Kind == k_Immediate; }
442
0
  bool isMem() const override { return false; }
443
0
  bool isSImm9() const {
444
0
    if (!isImm())
445
0
      return false;
446
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
447
0
    if (!MCE)
448
0
      return false;
449
0
    int64_t Val = MCE->getValue();
450
0
    return (Val >= -256 && Val < 256);
451
0
  }
452
0
  bool isSImm7s4() const {
453
0
    if (!isImm())
454
0
      return false;
455
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
456
0
    if (!MCE)
457
0
      return false;
458
0
    int64_t Val = MCE->getValue();
459
0
    return (Val >= -256 && Val <= 252 && (Val & 3) == 0);
460
0
  }
461
0
  bool isSImm7s8() const {
462
0
    if (!isImm())
463
0
      return false;
464
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
465
0
    if (!MCE)
466
0
      return false;
467
0
    int64_t Val = MCE->getValue();
468
0
    return (Val >= -512 && Val <= 504 && (Val & 7) == 0);
469
0
  }
470
0
  bool isSImm7s16() const {
471
0
    if (!isImm())
472
0
      return false;
473
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
474
0
    if (!MCE)
475
0
      return false;
476
0
    int64_t Val = MCE->getValue();
477
0
    return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0);
478
0
  }
479
480
0
  bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
481
0
    AArch64MCExpr::VariantKind ELFRefKind;
482
0
    MCSymbolRefExpr::VariantKind DarwinRefKind;
483
0
    int64_t Addend;
484
0
    if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
485
0
                                           Addend)) {
486
      // If we don't understand the expression, assume the best and
487
      // let the fixup and relocation code deal with it.
488
0
      return true;
489
0
    }
490
491
0
    if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
492
0
        ELFRefKind == AArch64MCExpr::VK_LO12 ||
493
0
        ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
494
0
        ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
495
0
        ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
496
0
        ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
497
0
        ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
498
0
        ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
499
0
        ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) {
500
      // Note that we don't range-check the addend. It's adjusted modulo page
501
      // size when converted, so there is no "out of range" condition when using
502
      // @pageoff.
503
0
      return Addend >= 0 && (Addend % Scale) == 0;
504
0
    } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
505
0
               DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
506
      // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
507
0
      return Addend == 0;
508
0
    }
509
510
0
    return false;
511
0
  }
512
513
0
  template <int Scale> bool isUImm12Offset() const {
514
0
    if (!isImm())
515
0
      return false;
516
517
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
518
0
    if (!MCE)
519
0
      return isSymbolicUImm12Offset(getImm(), Scale);
520
521
0
    int64_t Val = MCE->getValue();
522
0
    return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
523
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isUImm12Offset<16>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isUImm12Offset<1>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isUImm12Offset<2>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isUImm12Offset<4>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isUImm12Offset<8>() const
524
525
0
  bool isImm0_1() const {
526
0
    if (!isImm())
527
0
      return false;
528
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
529
0
    if (!MCE)
530
0
      return false;
531
0
    int64_t Val = MCE->getValue();
532
0
    return (Val >= 0 && Val < 2);
533
0
  }
534
0
  bool isImm0_7() const {
535
0
    if (!isImm())
536
0
      return false;
537
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
538
0
    if (!MCE)
539
0
      return false;
540
0
    int64_t Val = MCE->getValue();
541
0
    return (Val >= 0 && Val < 8);
542
0
  }
543
0
  bool isImm1_8() const {
544
0
    if (!isImm())
545
0
      return false;
546
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
547
0
    if (!MCE)
548
0
      return false;
549
0
    int64_t Val = MCE->getValue();
550
0
    return (Val > 0 && Val < 9);
551
0
  }
552
0
  bool isImm0_15() const {
553
0
    if (!isImm())
554
0
      return false;
555
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
556
0
    if (!MCE)
557
0
      return false;
558
0
    int64_t Val = MCE->getValue();
559
0
    return (Val >= 0 && Val < 16);
560
0
  }
561
0
  bool isImm1_16() const {
562
0
    if (!isImm())
563
0
      return false;
564
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
565
0
    if (!MCE)
566
0
      return false;
567
0
    int64_t Val = MCE->getValue();
568
0
    return (Val > 0 && Val < 17);
569
0
  }
570
0
  bool isImm0_31() const {
571
0
    if (!isImm())
572
0
      return false;
573
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
574
0
    if (!MCE)
575
0
      return false;
576
0
    int64_t Val = MCE->getValue();
577
0
    return (Val >= 0 && Val < 32);
578
0
  }
579
0
  bool isImm1_31() const {
580
0
    if (!isImm())
581
0
      return false;
582
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
583
0
    if (!MCE)
584
0
      return false;
585
0
    int64_t Val = MCE->getValue();
586
0
    return (Val >= 1 && Val < 32);
587
0
  }
588
0
  bool isImm1_32() const {
589
0
    if (!isImm())
590
0
      return false;
591
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
592
0
    if (!MCE)
593
0
      return false;
594
0
    int64_t Val = MCE->getValue();
595
0
    return (Val >= 1 && Val < 33);
596
0
  }
597
0
  bool isImm0_63() const {
598
0
    if (!isImm())
599
0
      return false;
600
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
601
0
    if (!MCE)
602
0
      return false;
603
0
    int64_t Val = MCE->getValue();
604
0
    return (Val >= 0 && Val < 64);
605
0
  }
606
0
  bool isImm1_63() const {
607
0
    if (!isImm())
608
0
      return false;
609
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
610
0
    if (!MCE)
611
0
      return false;
612
0
    int64_t Val = MCE->getValue();
613
0
    return (Val >= 1 && Val < 64);
614
0
  }
615
0
  bool isImm1_64() const {
616
0
    if (!isImm())
617
0
      return false;
618
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
619
0
    if (!MCE)
620
0
      return false;
621
0
    int64_t Val = MCE->getValue();
622
0
    return (Val >= 1 && Val < 65);
623
0
  }
624
2
  bool isImm0_127() const {
625
2
    if (!isImm())
626
0
      return false;
627
2
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
628
2
    if (!MCE)
629
0
      return false;
630
2
    int64_t Val = MCE->getValue();
631
2
    return (Val >= 0 && Val < 128);
632
2
  }
633
0
  bool isImm0_255() const {
634
0
    if (!isImm())
635
0
      return false;
636
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
637
0
    if (!MCE)
638
0
      return false;
639
0
    int64_t Val = MCE->getValue();
640
0
    return (Val >= 0 && Val < 256);
641
0
  }
642
12
  bool isImm0_65535() const {
643
12
    if (!isImm())
644
0
      return false;
645
12
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
646
12
    if (!MCE)
647
0
      return false;
648
12
    int64_t Val = MCE->getValue();
649
12
    return (Val >= 0 && Val < 65536);
650
12
  }
651
0
  bool isImm32_63() const {
652
0
    if (!isImm())
653
0
      return false;
654
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
655
0
    if (!MCE)
656
0
      return false;
657
0
    int64_t Val = MCE->getValue();
658
0
    return (Val >= 32 && Val < 64);
659
0
  }
660
2
  bool isLogicalImm32() const {
661
2
    if (!isImm())
662
0
      return false;
663
2
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
664
2
    if (!MCE)
665
0
      return false;
666
2
    int64_t Val = MCE->getValue();
667
2
    if (Val >> 32 != 0 && Val >> 32 != ~0LL)
668
2
      return false;
669
0
    Val &= 0xFFFFFFFF;
670
0
    return AArch64_AM::isLogicalImmediate(Val, 32);
671
2
  }
672
0
  bool isLogicalImm64() const {
673
0
    if (!isImm())
674
0
      return false;
675
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
676
0
    if (!MCE)
677
0
      return false;
678
0
    return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
679
0
  }
680
0
  bool isLogicalImm32Not() const {
681
0
    if (!isImm())
682
0
      return false;
683
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
684
0
    if (!MCE)
685
0
      return false;
686
0
    int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
687
0
    return AArch64_AM::isLogicalImmediate(Val, 32);
688
0
  }
689
0
  bool isLogicalImm64Not() const {
690
0
    if (!isImm())
691
0
      return false;
692
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
693
0
    if (!MCE)
694
0
      return false;
695
0
    return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
696
0
  }
697
51
  bool isShiftedImm() const { return Kind == k_ShiftedImm; }
698
7
  bool isAddSubImm() const {
699
7
    if (!isShiftedImm() && !isImm())
700
0
      return false;
701
702
7
    const MCExpr *Expr;
703
704
    // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
705
7
    if (isShiftedImm()) {
706
7
      unsigned Shift = ShiftedImm.ShiftAmount;
707
7
      Expr = ShiftedImm.Val;
708
7
      if (Shift != 0 && Shift != 12)
709
0
        return false;
710
7
    } else {
711
0
      Expr = getImm();
712
0
    }
713
714
7
    AArch64MCExpr::VariantKind ELFRefKind;
715
7
    MCSymbolRefExpr::VariantKind DarwinRefKind;
716
7
    int64_t Addend;
717
7
    if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
718
7
                                          DarwinRefKind, Addend)) {
719
0
      return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
720
0
          || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
721
0
          || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
722
0
          || ELFRefKind == AArch64MCExpr::VK_LO12
723
0
          || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
724
0
          || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
725
0
          || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
726
0
          || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
727
0
          || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
728
0
          || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
729
0
          || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12;
730
0
    }
731
732
    // Otherwise it should be a real immediate in range:
733
7
    const MCConstantExpr *CE = cast<MCConstantExpr>(Expr);
734
7
    return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
735
7
  }
736
11
  bool isAddSubImmNeg() const {
737
11
    if (!isShiftedImm() && !isImm())
738
0
      return false;
739
740
11
    const MCExpr *Expr;
741
742
    // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
743
11
    if (isShiftedImm()) {
744
11
      unsigned Shift = ShiftedImm.ShiftAmount;
745
11
      Expr = ShiftedImm.Val;
746
11
      if (Shift != 0 && Shift != 12)
747
0
        return false;
748
11
    } else
749
0
      Expr = getImm();
750
751
    // Otherwise it should be a real negative immediate in range:
752
11
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
753
11
    return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
754
11
  }
755
393
  bool isCondCode() const { return Kind == k_CondCode; }
756
0
  bool isSIMDImmType10() const {
757
0
    if (!isImm())
758
0
      return false;
759
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
760
0
    if (!MCE)
761
0
      return false;
762
0
    return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
763
0
  }
764
1.08k
  bool isBranchTarget26() const {
765
1.08k
    if (!isImm())
766
0
      return false;
767
1.08k
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
768
1.08k
    if (!MCE)
769
1.08k
      return true;
770
1
    int64_t Val = MCE->getValue();
771
1
    return ((Val & 0x3) == 0);
772
1.08k
  }
773
405
  bool isPCRelLabel19() const {
774
405
    if (!isImm())
775
0
      return false;
776
405
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
777
405
    if (!MCE)
778
375
      return true;
779
30
    int64_t Val = MCE->getValue();
780
30
    return ((Val & 0x3) == 0);
781
405
  }
782
0
  bool isBranchTarget14() const {
783
0
    if (!isImm())
784
0
      return false;
785
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
786
0
    if (!MCE)
787
0
      return true;
788
0
    int64_t Val = MCE->getValue();
789
0
    return ((Val & 0x3) == 0);
790
0
  }
791
792
  bool
793
4
  isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
794
4
    if (!isImm())
795
0
      return false;
796
797
4
    AArch64MCExpr::VariantKind ELFRefKind;
798
4
    MCSymbolRefExpr::VariantKind DarwinRefKind;
799
4
    int64_t Addend;
800
4
    if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
801
4
                                             DarwinRefKind, Addend)) {
802
4
      return false;
803
4
    }
804
0
    if (DarwinRefKind != MCSymbolRefExpr::VK_None)
805
0
      return false;
806
807
0
    for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
808
0
      if (ELFRefKind == AllowedModifiers[i])
809
0
        return Addend == 0;
810
0
    }
811
812
0
    return false;
813
0
  }
814
815
1
  bool isMovZSymbolG3() const {
816
1
    return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
817
1
  }
818
819
1
  bool isMovZSymbolG2() const {
820
1
    return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
821
1
                         AArch64MCExpr::VK_TPREL_G2,
822
1
                         AArch64MCExpr::VK_DTPREL_G2});
823
1
  }
824
825
1
  bool isMovZSymbolG1() const {
826
1
    return isMovWSymbol({
827
1
        AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
828
1
        AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
829
1
        AArch64MCExpr::VK_DTPREL_G1,
830
1
    });
831
1
  }
832
833
1
  bool isMovZSymbolG0() const {
834
1
    return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
835
1
                         AArch64MCExpr::VK_TPREL_G0,
836
1
                         AArch64MCExpr::VK_DTPREL_G0});
837
1
  }
838
839
0
  bool isMovKSymbolG3() const {
840
0
    return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
841
0
  }
842
843
0
  bool isMovKSymbolG2() const {
844
0
    return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
845
0
  }
846
847
0
  bool isMovKSymbolG1() const {
848
0
    return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
849
0
                         AArch64MCExpr::VK_TPREL_G1_NC,
850
0
                         AArch64MCExpr::VK_DTPREL_G1_NC});
851
0
  }
852
853
0
  bool isMovKSymbolG0() const {
854
0
    return isMovWSymbol(
855
0
        {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
856
0
         AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
857
0
  }
858
859
  template<int RegWidth, int Shift>
860
4
  bool isMOVZMovAlias() const {
861
4
    if (!isImm()) return false;
862
863
4
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
864
4
    if (!CE) return false;
865
4
    uint64_t Value = CE->getValue();
866
867
4
    if (RegWidth == 32)
868
4
      Value &= 0xffffffffULL;
869
870
    // "lsl #0" takes precedence: in practice this only affects "#0, lsl #0".
871
4
    if (Value == 0 && Shift != 0)
872
0
      return false;
873
874
4
    return (Value & ~(0xffffULL << Shift)) == 0;
875
4
  }
AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVZMovAlias<32, 0>() const
Line
Count
Source
860
2
  bool isMOVZMovAlias() const {
861
2
    if (!isImm()) return false;
862
863
2
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
864
2
    if (!CE) return false;
865
2
    uint64_t Value = CE->getValue();
866
867
2
    if (RegWidth == 32)
868
2
      Value &= 0xffffffffULL;
869
870
    // "lsl #0" takes precedence: in practice this only affects "#0, lsl #0".
871
2
    if (Value == 0 && Shift != 0)
872
0
      return false;
873
874
2
    return (Value & ~(0xffffULL << Shift)) == 0;
875
2
  }
AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVZMovAlias<32, 16>() const
Line
Count
Source
860
2
  bool isMOVZMovAlias() const {
861
2
    if (!isImm()) return false;
862
863
2
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
864
2
    if (!CE) return false;
865
2
    uint64_t Value = CE->getValue();
866
867
2
    if (RegWidth == 32)
868
2
      Value &= 0xffffffffULL;
869
870
    // "lsl #0" takes precedence: in practice this only affects "#0, lsl #0".
871
2
    if (Value == 0 && Shift != 0)
872
0
      return false;
873
874
2
    return (Value & ~(0xffffULL << Shift)) == 0;
875
2
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVZMovAlias<64, 16>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVZMovAlias<64, 32>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVZMovAlias<64, 48>() const
876
877
  template<int RegWidth, int Shift>
878
4
  bool isMOVNMovAlias() const {
879
4
    if (!isImm()) return false;
880
881
4
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
882
4
    if (!CE) return false;
883
4
    uint64_t Value = CE->getValue();
884
885
    // MOVZ takes precedence over MOVN.
886
20
    for (int MOVZShift = 0; MOVZShift <= 48; MOVZShift += 16)
887
16
      if ((Value & ~(0xffffULL << MOVZShift)) == 0)
888
0
        return false;
889
890
4
    Value = ~Value;
891
4
    if (RegWidth == 32)
892
4
      Value &= 0xffffffffULL;
893
894
4
    return (Value & ~(0xffffULL << Shift)) == 0;
895
4
  }
AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVNMovAlias<32, 0>() const
Line
Count
Source
878
2
  bool isMOVNMovAlias() const {
879
2
    if (!isImm()) return false;
880
881
2
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
882
2
    if (!CE) return false;
883
2
    uint64_t Value = CE->getValue();
884
885
    // MOVZ takes precedence over MOVN.
886
10
    for (int MOVZShift = 0; MOVZShift <= 48; MOVZShift += 16)
887
8
      if ((Value & ~(0xffffULL << MOVZShift)) == 0)
888
0
        return false;
889
890
2
    Value = ~Value;
891
2
    if (RegWidth == 32)
892
2
      Value &= 0xffffffffULL;
893
894
2
    return (Value & ~(0xffffULL << Shift)) == 0;
895
2
  }
AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVNMovAlias<32, 16>() const
Line
Count
Source
878
2
  bool isMOVNMovAlias() const {
879
2
    if (!isImm()) return false;
880
881
2
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
882
2
    if (!CE) return false;
883
2
    uint64_t Value = CE->getValue();
884
885
    // MOVZ takes precedence over MOVN.
886
10
    for (int MOVZShift = 0; MOVZShift <= 48; MOVZShift += 16)
887
8
      if ((Value & ~(0xffffULL << MOVZShift)) == 0)
888
0
        return false;
889
890
2
    Value = ~Value;
891
2
    if (RegWidth == 32)
892
2
      Value &= 0xffffffffULL;
893
894
2
    return (Value & ~(0xffffULL << Shift)) == 0;
895
2
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVNMovAlias<64, 0>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVNMovAlias<64, 16>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVNMovAlias<64, 32>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMOVNMovAlias<64, 48>() const
896
897
1
  bool isFPImm() const { return Kind == k_FPImm; }
898
50
  bool isBarrier() const { return Kind == k_Barrier; }
899
16
  bool isSysReg() const { return Kind == k_SysReg; }
900
0
  bool isMRSSystemRegister() const {
901
0
    if (!isSysReg()) return false;
902
903
0
    return SysReg.MRSReg != -1U;
904
0
  }
905
4
  bool isMSRSystemRegister() const {
906
4
    if (!isSysReg()) return false;
907
4
    return SysReg.MSRReg != -1U;
908
4
  }
909
8
  bool isSystemPStateFieldWithImm0_1() const {
910
8
    if (!isSysReg()) return false;
911
8
    return (SysReg.PStateField == AArch64PState::PAN ||
912
8
            SysReg.PStateField == AArch64PState::UAO);
913
8
  }
914
4
  bool isSystemPStateFieldWithImm0_15() const {
915
4
    if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
916
4
    return SysReg.PStateField != -1U;
917
4
  }
918
2.73k
  bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
919
49
  bool isVectorReg() const { return Kind == k_Register && Reg.isVector; }
920
0
  bool isVectorRegLo() const {
921
0
    return Kind == k_Register && Reg.isVector &&
922
0
           AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
923
0
               Reg.RegNum);
924
0
  }
925
0
  bool isGPR32as64() const {
926
0
    return Kind == k_Register && !Reg.isVector &&
927
0
      AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
928
0
  }
929
0
  bool isWSeqPair() const {
930
0
    return Kind == k_Register && !Reg.isVector &&
931
0
           AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
932
0
               Reg.RegNum);
933
0
  }
934
0
  bool isXSeqPair() const {
935
0
    return Kind == k_Register && !Reg.isVector &&
936
0
           AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
937
0
               Reg.RegNum);
938
0
  }
939
940
0
  bool isGPR64sp0() const {
941
0
    return Kind == k_Register && !Reg.isVector &&
942
0
      AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
943
0
  }
944
945
  /// Is this a vector list with the type implicit (presumably attached to the
946
  /// instruction itself)?
947
0
  template <unsigned NumRegs> bool isImplicitlyTypedVectorList() const {
948
0
    return Kind == k_VectorList && VectorList.Count == NumRegs &&
949
0
           !VectorList.ElementKind;
950
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isImplicitlyTypedVectorList<4u>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isImplicitlyTypedVectorList<1u>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isImplicitlyTypedVectorList<3u>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isImplicitlyTypedVectorList<2u>() const
951
952
  template <unsigned NumRegs, unsigned NumElements, char ElementKind>
953
0
  bool isTypedVectorList() const {
954
0
    if (Kind != k_VectorList)
955
0
      return false;
956
0
    if (VectorList.Count != NumRegs)
957
0
      return false;
958
0
    if (VectorList.ElementKind != ElementKind)
959
0
      return false;
960
0
    return VectorList.NumElements == NumElements;
961
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 16u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 1u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 2u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 2u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 4u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 4u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 8u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 8u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 0u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 0u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 0u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<4u, 0u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 16u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 1u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 2u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 2u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 4u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 4u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 8u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 8u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 0u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 0u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 0u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<1u, 0u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 16u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 1u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 2u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 2u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 4u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 4u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 8u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 8u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 0u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 0u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 0u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<3u, 0u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 16u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 1u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 2u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 2u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 4u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 4u, (char)115>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 8u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 8u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 0u, (char)98>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 0u, (char)100>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 0u, (char)104>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isTypedVectorList<2u, 0u, (char)115>() const
962
963
0
  bool isVectorIndex1() const {
964
0
    return Kind == k_VectorIndex && VectorIndex.Val == 1;
965
0
  }
966
0
  bool isVectorIndexB() const {
967
0
    return Kind == k_VectorIndex && VectorIndex.Val < 16;
968
0
  }
969
0
  bool isVectorIndexH() const {
970
0
    return Kind == k_VectorIndex && VectorIndex.Val < 8;
971
0
  }
972
0
  bool isVectorIndexS() const {
973
0
    return Kind == k_VectorIndex && VectorIndex.Val < 4;
974
0
  }
975
0
  bool isVectorIndexD() const {
976
0
    return Kind == k_VectorIndex && VectorIndex.Val < 2;
977
0
  }
978
7.36k
  bool isToken() const override { return Kind == k_Token; }
979
0
  bool isTokenEqual(StringRef Str) const {
980
0
    return Kind == k_Token && getToken() == Str;
981
0
  }
982
0
  bool isSysCR() const { return Kind == k_SysCR; }
983
0
  bool isPrefetch() const { return Kind == k_Prefetch; }
984
0
  bool isPSBHint() const { return Kind == k_PSBHint; }
985
1
  bool isShiftExtend() const { return Kind == k_ShiftExtend; }
986
1
  bool isShifter() const {
987
1
    if (!isShiftExtend())
988
0
      return false;
989
990
1
    AArch64_AM::ShiftExtendType ST = getShiftExtendType();
991
1
    return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
992
0
            ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
993
0
            ST == AArch64_AM::MSL);
994
1
  }
995
0
  bool isExtend() const {
996
0
    if (!isShiftExtend())
997
0
      return false;
998
999
0
    AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1000
0
    return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1001
0
            ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1002
0
            ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1003
0
            ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1004
0
            ET == AArch64_AM::LSL) &&
1005
0
           getShiftExtendAmount() <= 4;
1006
0
  }
1007
1008
0
  bool isExtend64() const {
1009
0
    if (!isExtend())
1010
0
      return false;
1011
    // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1012
0
    AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1013
0
    return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1014
0
  }
1015
0
  bool isExtendLSL64() const {
1016
0
    if (!isExtend())
1017
0
      return false;
1018
0
    AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1019
0
    return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1020
0
            ET == AArch64_AM::LSL) &&
1021
0
           getShiftExtendAmount() <= 4;
1022
0
  }
1023
1024
0
  template<int Width> bool isMemXExtend() const {
1025
0
    if (!isExtend())
1026
0
      return false;
1027
0
    AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1028
0
    return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1029
0
           (getShiftExtendAmount() == Log2_32(Width / 8) ||
1030
0
            getShiftExtendAmount() == 0);
1031
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemXExtend<128>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemXExtend<16>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemXExtend<32>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemXExtend<64>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemXExtend<8>() const
1032
1033
0
  template<int Width> bool isMemWExtend() const {
1034
0
    if (!isExtend())
1035
0
      return false;
1036
0
    AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1037
0
    return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1038
0
           (getShiftExtendAmount() == Log2_32(Width / 8) ||
1039
0
            getShiftExtendAmount() == 0);
1040
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemWExtend<128>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemWExtend<16>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemWExtend<32>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemWExtend<64>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isMemWExtend<8>() const
1041
1042
  template <unsigned width>
1043
0
  bool isArithmeticShifter() const {
1044
0
    if (!isShifter())
1045
0
      return false;
1046
1047
    // An arithmetic shifter is LSL, LSR, or ASR.
1048
0
    AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1049
0
    return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1050
0
            ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1051
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isArithmeticShifter<32u>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isArithmeticShifter<64u>() const
1052
1053
  template <unsigned width>
1054
0
  bool isLogicalShifter() const {
1055
0
    if (!isShifter())
1056
0
      return false;
1057
1058
    // A logical shifter is LSL, LSR, ASR or ROR.
1059
0
    AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1060
0
    return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1061
0
            ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1062
0
           getShiftExtendAmount() < width;
1063
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isLogicalShifter<32u>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isLogicalShifter<64u>() const
1064
1065
0
  bool isMovImm32Shifter() const {
1066
0
    if (!isShifter())
1067
0
      return false;
1068
1069
    // A MOVi shifter is LSL of 0, 16, 32, or 48.
1070
0
    AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1071
0
    if (ST != AArch64_AM::LSL)
1072
0
      return false;
1073
0
    uint64_t Val = getShiftExtendAmount();
1074
0
    return (Val == 0 || Val == 16);
1075
0
  }
1076
1077
1
  bool isMovImm64Shifter() const {
1078
1
    if (!isShifter())
1079
0
      return false;
1080
1081
    // A MOVi shifter is LSL of 0 or 16.
1082
1
    AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1083
1
    if (ST != AArch64_AM::LSL)
1084
0
      return false;
1085
1
    uint64_t Val = getShiftExtendAmount();
1086
1
    return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1087
1
  }
1088
1089
0
  bool isLogicalVecShifter() const {
1090
0
    if (!isShifter())
1091
0
      return false;
1092
1093
    // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1094
0
    unsigned Shift = getShiftExtendAmount();
1095
0
    return getShiftExtendType() == AArch64_AM::LSL &&
1096
0
           (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1097
0
  }
1098
1099
0
  bool isLogicalVecHalfWordShifter() const {
1100
0
    if (!isLogicalVecShifter())
1101
0
      return false;
1102
1103
    // A logical vector shifter is a left shift by 0 or 8.
1104
0
    unsigned Shift = getShiftExtendAmount();
1105
0
    return getShiftExtendType() == AArch64_AM::LSL &&
1106
0
           (Shift == 0 || Shift == 8);
1107
0
  }
1108
1109
0
  bool isMoveVecShifter() const {
1110
0
    if (!isShiftExtend())
1111
0
      return false;
1112
1113
    // A logical vector shifter is a left shift by 8 or 16.
1114
0
    unsigned Shift = getShiftExtendAmount();
1115
0
    return getShiftExtendType() == AArch64_AM::MSL &&
1116
0
           (Shift == 8 || Shift == 16);
1117
0
  }
1118
1119
  // Fallback unscaled operands are for aliases of LDR/STR that fall back
1120
  // to LDUR/STUR when the offset is not legal for the former but is for
1121
  // the latter. As such, in addition to checking for being a legal unscaled
1122
  // address, also check that it is not a legal scaled address. This avoids
1123
  // ambiguity in the matcher.
1124
  template<int Width>
1125
0
  bool isSImm9OffsetFB() const {
1126
0
    return isSImm9() && !isUImm12Offset<Width / 8>();
1127
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isSImm9OffsetFB<128>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isSImm9OffsetFB<16>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isSImm9OffsetFB<32>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isSImm9OffsetFB<64>() const
Unexecuted instantiation: AArch64AsmParser.cpp:bool (anonymous namespace)::AArch64Operand::isSImm9OffsetFB<8>() const
1128
1129
0
  bool isAdrpLabel() const {
1130
    // Validation was handled during parsing, so we just sanity check that
1131
    // something didn't go haywire.
1132
0
    if (!isImm())
1133
0
        return false;
1134
1135
0
    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1136
0
      int64_t Val = CE->getValue();
1137
0
      int64_t Offset = Val - Ctx.getBaseAddress();
1138
0
      int64_t Min = - (4096 * (1LL << (21 - 1)));
1139
0
      int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1140
0
      return (Val % 4096) == 0 && Offset >= Min && Offset <= Max;
1141
0
    }
1142
1143
0
    return true;
1144
0
  }
1145
1146
0
  bool isAdrLabel() const {
1147
    // Validation was handled during parsing, so we just sanity check that
1148
    // something didn't go haywire.
1149
0
    if (!isImm())
1150
0
        return false;
1151
1152
0
    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1153
0
      int64_t Val = CE->getValue();
1154
0
      int64_t Min = - (1LL << (21 - 1));
1155
0
      int64_t Max = ((1LL << (21 - 1)) - 1);
1156
0
      return Val >= Min && Val <= Max;
1157
0
    }
1158
1159
0
    return true;
1160
0
  }
1161
1162
1.46k
  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1163
    // Add as immediates when possible.  Null MCExpr = 0.
1164
1.46k
    if (!Expr)
1165
0
      Inst.addOperand(MCOperand::createImm(0));
1166
1.46k
    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1167
7
      Inst.addOperand(MCOperand::createImm(CE->getValue()));
1168
1.46k
    else
1169
1.46k
      Inst.addOperand(MCOperand::createExpr(Expr));
1170
1.46k
  }
1171
1172
327
  void addRegOperands(MCInst &Inst, unsigned N) const {
1173
327
    assert(N == 1 && "Invalid number of operands!");
1174
327
    Inst.addOperand(MCOperand::createReg(getReg()));
1175
327
  }
1176
1177
0
  void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1178
0
    assert(N == 1 && "Invalid number of operands!");
1179
0
    assert(
1180
0
        AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1181
1182
0
    const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1183
0
    uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1184
0
        RI->getEncodingValue(getReg()));
1185
1186
0
    Inst.addOperand(MCOperand::createReg(Reg));
1187
0
  }
1188
1189
0
  void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1190
0
    assert(N == 1 && "Invalid number of operands!");
1191
0
    assert(
1192
0
        AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
1193
0
    Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
1194
0
  }
1195
1196
0
  void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1197
0
    assert(N == 1 && "Invalid number of operands!");
1198
0
    assert(
1199
0
        AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
1200
0
    Inst.addOperand(MCOperand::createReg(getReg()));
1201
0
  }
1202
1203
0
  void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1204
0
    assert(N == 1 && "Invalid number of operands!");
1205
0
    Inst.addOperand(MCOperand::createReg(getReg()));
1206
0
  }
1207
1208
  template <unsigned NumRegs>
1209
0
  void addVectorList64Operands(MCInst &Inst, unsigned N) const {
1210
0
    assert(N == 1 && "Invalid number of operands!");
1211
0
    static const unsigned FirstRegs[] = { AArch64::D0,
1212
0
                                          AArch64::D0_D1,
1213
0
                                          AArch64::D0_D1_D2,
1214
0
                                          AArch64::D0_D1_D2_D3 };
1215
0
    unsigned FirstReg = FirstRegs[NumRegs - 1];
1216
1217
0
    Inst.addOperand(
1218
0
        MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
1219
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addVectorList64Operands<4u>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addVectorList64Operands<1u>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addVectorList64Operands<3u>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addVectorList64Operands<2u>(llvm_ks::MCInst&, unsigned int) const
1220
1221
  template <unsigned NumRegs>
1222
0
  void addVectorList128Operands(MCInst &Inst, unsigned N) const {
1223
0
    assert(N == 1 && "Invalid number of operands!");
1224
0
    static const unsigned FirstRegs[] = { AArch64::Q0,
1225
0
                                          AArch64::Q0_Q1,
1226
0
                                          AArch64::Q0_Q1_Q2,
1227
0
                                          AArch64::Q0_Q1_Q2_Q3 };
1228
0
    unsigned FirstReg = FirstRegs[NumRegs - 1];
1229
1230
0
    Inst.addOperand(
1231
0
        MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0));
1232
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addVectorList128Operands<4u>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addVectorList128Operands<1u>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addVectorList128Operands<3u>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addVectorList128Operands<2u>(llvm_ks::MCInst&, unsigned int) const
1233
1234
0
  void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1235
0
    assert(N == 1 && "Invalid number of operands!");
1236
0
    Inst.addOperand(MCOperand::createImm(getVectorIndex()));
1237
0
  }
1238
1239
0
  void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1240
0
    assert(N == 1 && "Invalid number of operands!");
1241
0
    Inst.addOperand(MCOperand::createImm(getVectorIndex()));
1242
0
  }
1243
1244
0
  void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1245
0
    assert(N == 1 && "Invalid number of operands!");
1246
0
    Inst.addOperand(MCOperand::createImm(getVectorIndex()));
1247
0
  }
1248
1249
0
  void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1250
0
    assert(N == 1 && "Invalid number of operands!");
1251
0
    Inst.addOperand(MCOperand::createImm(getVectorIndex()));
1252
0
  }
1253
1254
0
  void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1255
0
    assert(N == 1 && "Invalid number of operands!");
1256
0
    Inst.addOperand(MCOperand::createImm(getVectorIndex()));
1257
0
  }
1258
1259
0
  void addImmOperands(MCInst &Inst, unsigned N) const {
1260
0
    assert(N == 1 && "Invalid number of operands!");
1261
    // If this is a pageoff symrefexpr with an addend, adjust the addend
1262
    // to be only the page-offset portion. Otherwise, just add the expr
1263
    // as-is.
1264
0
    addExpr(Inst, getImm());
1265
0
  }
1266
1267
7
  void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1268
7
    assert(N == 2 && "Invalid number of operands!");
1269
7
    if (isShiftedImm()) {
1270
7
      addExpr(Inst, getShiftedImmVal());
1271
7
      Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
1272
7
    } else {
1273
0
      addExpr(Inst, getImm());
1274
0
      Inst.addOperand(MCOperand::createImm(0));
1275
0
    }
1276
7
  }
1277
1278
4
  void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1279
4
    assert(N == 2 && "Invalid number of operands!");
1280
1281
4
    const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1282
4
    const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1283
4
    int64_t Val = -CE->getValue();
1284
4
    unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1285
1286
4
    Inst.addOperand(MCOperand::createImm(Val));
1287
4
    Inst.addOperand(MCOperand::createImm(ShiftAmt));
1288
4
  }
1289
1290
389
  void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1291
389
    assert(N == 1 && "Invalid number of operands!");
1292
389
    Inst.addOperand(MCOperand::createImm(getCondCode()));
1293
389
  }
1294
1295
0
  void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1296
0
    assert(N == 1 && "Invalid number of operands!");
1297
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1298
0
    if (!MCE)
1299
0
      addExpr(Inst, getImm());
1300
0
    else
1301
0
      Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
1302
0
  }
1303
1304
0
  void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1305
0
    addImmOperands(Inst, N);
1306
0
  }
1307
1308
  template<int Scale>
1309
0
  void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1310
0
    assert(N == 1 && "Invalid number of operands!");
1311
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1312
1313
0
    if (!MCE) {
1314
0
      Inst.addOperand(MCOperand::createExpr(getImm()));
1315
0
      return;
1316
0
    }
1317
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1318
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addUImm12OffsetOperands<16>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addUImm12OffsetOperands<2>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addUImm12OffsetOperands<4>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addUImm12OffsetOperands<8>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addUImm12OffsetOperands<1>(llvm_ks::MCInst&, unsigned int) const
1319
1320
0
  void addSImm9Operands(MCInst &Inst, unsigned N) const {
1321
0
    assert(N == 1 && "Invalid number of operands!");
1322
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1323
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1324
0
  }
1325
1326
0
  void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1327
0
    assert(N == 1 && "Invalid number of operands!");
1328
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1329
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
1330
0
  }
1331
1332
0
  void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1333
0
    assert(N == 1 && "Invalid number of operands!");
1334
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1335
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1336
0
  }
1337
1338
0
  void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1339
0
    assert(N == 1 && "Invalid number of operands!");
1340
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1341
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
1342
0
  }
1343
1344
0
  void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1345
0
    assert(N == 1 && "Invalid number of operands!");
1346
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1347
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1348
0
  }
1349
1350
0
  void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1351
0
    assert(N == 1 && "Invalid number of operands!");
1352
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1353
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1354
0
  }
1355
1356
0
  void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1357
0
    assert(N == 1 && "Invalid number of operands!");
1358
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1359
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1360
0
  }
1361
1362
0
  void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1363
0
    assert(N == 1 && "Invalid number of operands!");
1364
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1365
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1366
0
  }
1367
1368
0
  void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1369
0
    assert(N == 1 && "Invalid number of operands!");
1370
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1371
0
    assert(MCE && "Invalid constant immediate operand!");
1372
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1373
0
  }
1374
1375
0
  void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1376
0
    assert(N == 1 && "Invalid number of operands!");
1377
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1378
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1379
0
  }
1380
1381
0
  void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1382
0
    assert(N == 1 && "Invalid number of operands!");
1383
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1384
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1385
0
  }
1386
1387
0
  void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1388
0
    assert(N == 1 && "Invalid number of operands!");
1389
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1390
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1391
0
  }
1392
1393
0
  void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1394
0
    assert(N == 1 && "Invalid number of operands!");
1395
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1396
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1397
0
  }
1398
1399
0
  void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1400
0
    assert(N == 1 && "Invalid number of operands!");
1401
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1402
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1403
0
  }
1404
1405
0
  void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1406
0
    assert(N == 1 && "Invalid number of operands!");
1407
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1408
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1409
0
  }
1410
1411
0
  void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1412
0
    assert(N == 1 && "Invalid number of operands!");
1413
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1414
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1415
0
  }
1416
1417
0
  void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1418
0
    assert(N == 1 && "Invalid number of operands!");
1419
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1420
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1421
0
  }
1422
1423
11
  void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1424
11
    assert(N == 1 && "Invalid number of operands!");
1425
11
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1426
11
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1427
11
  }
1428
1429
0
  void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1430
0
    assert(N == 1 && "Invalid number of operands!");
1431
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1432
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1433
0
  }
1434
1435
0
  void addLogicalImm32Operands(MCInst &Inst, unsigned N) const {
1436
0
    assert(N == 1 && "Invalid number of operands!");
1437
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1438
0
    uint64_t encoding =
1439
0
        AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
1440
0
    Inst.addOperand(MCOperand::createImm(encoding));
1441
0
  }
1442
1443
0
  void addLogicalImm64Operands(MCInst &Inst, unsigned N) const {
1444
0
    assert(N == 1 && "Invalid number of operands!");
1445
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1446
0
    uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
1447
0
    Inst.addOperand(MCOperand::createImm(encoding));
1448
0
  }
1449
1450
0
  void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
1451
0
    assert(N == 1 && "Invalid number of operands!");
1452
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1453
0
    int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
1454
0
    uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
1455
0
    Inst.addOperand(MCOperand::createImm(encoding));
1456
0
  }
1457
1458
0
  void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
1459
0
    assert(N == 1 && "Invalid number of operands!");
1460
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1461
0
    uint64_t encoding =
1462
0
        AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
1463
0
    Inst.addOperand(MCOperand::createImm(encoding));
1464
0
  }
1465
1466
0
  void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1467
0
    assert(N == 1 && "Invalid number of operands!");
1468
0
    const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1469
0
    uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
1470
0
    Inst.addOperand(MCOperand::createImm(encoding));
1471
0
  }
1472
1473
1.08k
  void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1474
    // Branch operands don't encode the low bits, so shift them off
1475
    // here. If it's a label, however, just put it on directly as there's
1476
    // not enough information now to do anything.
1477
1.08k
    assert(N == 1 && "Invalid number of operands!");
1478
1.08k
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1479
1.08k
    if (!MCE) {
1480
1.08k
      addExpr(Inst, getImm());
1481
1.08k
      return;
1482
1.08k
    }
1483
1.08k
    assert(MCE && "Invalid constant immediate operand!");
1484
1
    Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
1485
1
  }
1486
1487
405
  void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1488
    // Branch operands don't encode the low bits, so shift them off
1489
    // here. If it's a label, however, just put it on directly as there's
1490
    // not enough information now to do anything.
1491
405
    assert(N == 1 && "Invalid number of operands!");
1492
405
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1493
405
    if (!MCE) {
1494
375
      addExpr(Inst, getImm());
1495
375
      return;
1496
375
    }
1497
405
    assert(MCE && "Invalid constant immediate operand!");
1498
30
    Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
1499
30
  }
1500
1501
0
  void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1502
    // Branch operands don't encode the low bits, so shift them off
1503
    // here. If it's a label, however, just put it on directly as there's
1504
    // not enough information now to do anything.
1505
0
    assert(N == 1 && "Invalid number of operands!");
1506
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1507
0
    if (!MCE) {
1508
0
      addExpr(Inst, getImm());
1509
0
      return;
1510
0
    }
1511
0
    assert(MCE && "Invalid constant immediate operand!");
1512
0
    Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
1513
0
  }
1514
1515
0
  void addFPImmOperands(MCInst &Inst, unsigned N) const {
1516
0
    assert(N == 1 && "Invalid number of operands!");
1517
0
    Inst.addOperand(MCOperand::createImm(getFPImm()));
1518
0
  }
1519
1520
50
  void addBarrierOperands(MCInst &Inst, unsigned N) const {
1521
50
    assert(N == 1 && "Invalid number of operands!");
1522
50
    Inst.addOperand(MCOperand::createImm(getBarrier()));
1523
50
  }
1524
1525
0
  void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1526
0
    assert(N == 1 && "Invalid number of operands!");
1527
1528
0
    Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
1529
0
  }
1530
1531
0
  void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1532
0
    assert(N == 1 && "Invalid number of operands!");
1533
1534
0
    Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
1535
0
  }
1536
1537
0
  void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1538
0
    assert(N == 1 && "Invalid number of operands!");
1539
1540
0
    Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1541
0
  }
1542
1543
0
  void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
1544
0
    assert(N == 1 && "Invalid number of operands!");
1545
1546
0
    Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1547
0
  }
1548
1549
0
  void addSysCROperands(MCInst &Inst, unsigned N) const {
1550
0
    assert(N == 1 && "Invalid number of operands!");
1551
0
    Inst.addOperand(MCOperand::createImm(getSysCR()));
1552
0
  }
1553
1554
0
  void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1555
0
    assert(N == 1 && "Invalid number of operands!");
1556
0
    Inst.addOperand(MCOperand::createImm(getPrefetch()));
1557
0
  }
1558
1559
0
  void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1560
0
    assert(N == 1 && "Invalid number of operands!");
1561
0
    Inst.addOperand(MCOperand::createImm(getPSBHint()));
1562
0
  }
1563
1564
1
  void addShifterOperands(MCInst &Inst, unsigned N) const {
1565
1
    assert(N == 1 && "Invalid number of operands!");
1566
1
    unsigned Imm =
1567
1
        AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
1568
1
    Inst.addOperand(MCOperand::createImm(Imm));
1569
1
  }
1570
1571
0
  void addExtendOperands(MCInst &Inst, unsigned N) const {
1572
0
    assert(N == 1 && "Invalid number of operands!");
1573
0
    AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1574
0
    if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1575
0
    unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
1576
0
    Inst.addOperand(MCOperand::createImm(Imm));
1577
0
  }
1578
1579
0
  void addExtend64Operands(MCInst &Inst, unsigned N) const {
1580
0
    assert(N == 1 && "Invalid number of operands!");
1581
0
    AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1582
0
    if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1583
0
    unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
1584
0
    Inst.addOperand(MCOperand::createImm(Imm));
1585
0
  }
1586
1587
0
  void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1588
0
    assert(N == 2 && "Invalid number of operands!");
1589
0
    AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1590
0
    bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
1591
0
    Inst.addOperand(MCOperand::createImm(IsSigned));
1592
0
    Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
1593
0
  }
1594
1595
  // For 8-bit load/store instructions with a register offset, both the
1596
  // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1597
  // they're disambiguated by whether the shift was explicit or implicit rather
1598
  // than its size.
1599
0
  void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1600
0
    assert(N == 2 && "Invalid number of operands!");
1601
0
    AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1602
0
    bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
1603
0
    Inst.addOperand(MCOperand::createImm(IsSigned));
1604
0
    Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
1605
0
  }
1606
1607
  template<int Shift>
1608
0
  void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1609
0
    assert(N == 1 && "Invalid number of operands!");
1610
1611
0
    const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1612
0
    uint64_t Value = CE->getValue();
1613
0
    Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
1614
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addMOVZMovAliasOperands<0>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addMOVZMovAliasOperands<16>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addMOVZMovAliasOperands<32>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addMOVZMovAliasOperands<48>(llvm_ks::MCInst&, unsigned int) const
1615
1616
  template<int Shift>
1617
0
  void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1618
0
    assert(N == 1 && "Invalid number of operands!");
1619
1620
0
    const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1621
0
    uint64_t Value = CE->getValue();
1622
0
    Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
1623
0
  }
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addMOVNMovAliasOperands<0>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addMOVNMovAliasOperands<16>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addMOVNMovAliasOperands<32>(llvm_ks::MCInst&, unsigned int) const
Unexecuted instantiation: AArch64AsmParser.cpp:void (anonymous namespace)::AArch64Operand::addMOVNMovAliasOperands<48>(llvm_ks::MCInst&, unsigned int) const
1624
1625
  void print(raw_ostream &OS) const override;
1626
1627
  static std::unique_ptr<AArch64Operand>
1628
96.5k
  CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1629
96.5k
    auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
1630
96.5k
    Op->Tok.Data = Str.data();
1631
96.5k
    Op->Tok.Length = Str.size();
1632
96.5k
    Op->Tok.IsSuffix = IsSuffix;
1633
96.5k
    Op->StartLoc = S;
1634
96.5k
    Op->EndLoc = S;
1635
96.5k
    return Op;
1636
96.5k
  }
1637
1638
  static std::unique_ptr<AArch64Operand>
1639
5.59k
  CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
1640
5.59k
    auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1641
5.59k
    Op->Reg.RegNum = RegNum;
1642
5.59k
    Op->Reg.isVector = isVector;
1643
5.59k
    Op->StartLoc = S;
1644
5.59k
    Op->EndLoc = E;
1645
5.59k
    return Op;
1646
5.59k
  }
1647
1648
  static std::unique_ptr<AArch64Operand>
1649
  CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1650
76
                   char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
1651
76
    auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
1652
76
    Op->VectorList.RegNum = RegNum;
1653
76
    Op->VectorList.Count = Count;
1654
76
    Op->VectorList.NumElements = NumElements;
1655
76
    Op->VectorList.ElementKind = ElementKind;
1656
76
    Op->StartLoc = S;
1657
76
    Op->EndLoc = E;
1658
76
    return Op;
1659
76
  }
1660
1661
  static std::unique_ptr<AArch64Operand>
1662
0
  CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1663
0
    auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
1664
0
    Op->VectorIndex.Val = Idx;
1665
0
    Op->StartLoc = S;
1666
0
    Op->EndLoc = E;
1667
0
    return Op;
1668
0
  }
1669
1670
  static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1671
22.0k
                                                   SMLoc E, MCContext &Ctx) {
1672
22.0k
    auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
1673
22.0k
    Op->Imm.Val = Val;
1674
22.0k
    Op->StartLoc = S;
1675
22.0k
    Op->EndLoc = E;
1676
22.0k
    return Op;
1677
22.0k
  }
1678
1679
  static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1680
                                                          unsigned ShiftAmount,
1681
                                                          SMLoc S, SMLoc E,
1682
12
                                                          MCContext &Ctx) {
1683
12
    auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
1684
12
    Op->ShiftedImm .Val = Val;
1685
12
    Op->ShiftedImm.ShiftAmount = ShiftAmount;
1686
12
    Op->StartLoc = S;
1687
12
    Op->EndLoc = E;
1688
12
    return Op;
1689
12
  }
1690
1691
  static std::unique_ptr<AArch64Operand>
1692
483
  CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1693
483
    auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
1694
483
    Op->CondCode.Code = Code;
1695
483
    Op->StartLoc = S;
1696
483
    Op->EndLoc = E;
1697
483
    return Op;
1698
483
  }
1699
1700
  static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1701
1
                                                     MCContext &Ctx) {
1702
1
    auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
1703
1
    Op->FPImm.Val = Val;
1704
1
    Op->StartLoc = S;
1705
1
    Op->EndLoc = S;
1706
1
    return Op;
1707
1
  }
1708
1709
  static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1710
                                                       StringRef Str,
1711
                                                       SMLoc S,
1712
50
                                                       MCContext &Ctx) {
1713
50
    auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
1714
50
    Op->Barrier.Val = Val;
1715
50
    Op->Barrier.Data = Str.data();
1716
50
    Op->Barrier.Length = Str.size();
1717
50
    Op->StartLoc = S;
1718
50
    Op->EndLoc = S;
1719
50
    return Op;
1720
50
  }
1721
1722
  static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1723
                                                      uint32_t MRSReg,
1724
                                                      uint32_t MSRReg,
1725
                                                      uint32_t PStateField,
1726
575
                                                      MCContext &Ctx) {
1727
575
    auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
1728
575
    Op->SysReg.Data = Str.data();
1729
575
    Op->SysReg.Length = Str.size();
1730
575
    Op->SysReg.MRSReg = MRSReg;
1731
575
    Op->SysReg.MSRReg = MSRReg;
1732
575
    Op->SysReg.PStateField = PStateField;
1733
575
    Op->StartLoc = S;
1734
575
    Op->EndLoc = S;
1735
575
    return Op;
1736
575
  }
1737
1738
  static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1739
0
                                                     SMLoc E, MCContext &Ctx) {
1740
0
    auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
1741
0
    Op->SysCRImm.Val = Val;
1742
0
    Op->StartLoc = S;
1743
0
    Op->EndLoc = E;
1744
0
    return Op;
1745
0
  }
1746
1747
  static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1748
                                                        StringRef Str,
1749
                                                        SMLoc S,
1750
0
                                                        MCContext &Ctx) {
1751
0
    auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
1752
0
    Op->Prefetch.Val = Val;
1753
0
    Op->Barrier.Data = Str.data();
1754
0
    Op->Barrier.Length = Str.size();
1755
0
    Op->StartLoc = S;
1756
0
    Op->EndLoc = S;
1757
0
    return Op;
1758
0
  }
1759
1760
  static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1761
                                                       StringRef Str,
1762
                                                       SMLoc S,
1763
0
                                                       MCContext &Ctx) {
1764
0
    auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1765
0
    Op->PSBHint.Val = Val;
1766
0
    Op->PSBHint.Data = Str.data();
1767
0
    Op->PSBHint.Length = Str.size();
1768
0
    Op->StartLoc = S;
1769
0
    Op->EndLoc = S;
1770
0
    return Op;
1771
0
  }
1772
1773
  static std::unique_ptr<AArch64Operand>
1774
  CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1775
275
                    bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1776
275
    auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
1777
275
    Op->ShiftExtend.Type = ShOp;
1778
275
    Op->ShiftExtend.Amount = Val;
1779
275
    Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1780
275
    Op->StartLoc = S;
1781
275
    Op->EndLoc = E;
1782
275
    return Op;
1783
275
  }
1784
};
1785
1786
} // end anonymous namespace.
1787
1788
0
void AArch64Operand::print(raw_ostream &OS) const {
1789
0
  switch (Kind) {
1790
0
  case k_FPImm:
1791
0
    OS << "<fpimm " << getFPImm() << "("
1792
0
       << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1793
0
    break;
1794
0
  case k_Barrier: {
1795
0
    StringRef Name = getBarrierName();
1796
0
    if (!Name.empty())
1797
0
      OS << "<barrier " << Name << ">";
1798
0
    else
1799
0
      OS << "<barrier invalid #" << getBarrier() << ">";
1800
0
    break;
1801
0
  }
1802
0
  case k_Immediate:
1803
0
    OS << *getImm();
1804
0
    break;
1805
0
  case k_ShiftedImm: {
1806
0
    unsigned Shift = getShiftedImmShift();
1807
0
    OS << "<shiftedimm ";
1808
0
    OS << *getShiftedImmVal();
1809
0
    OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1810
0
    break;
1811
0
  }
1812
0
  case k_CondCode:
1813
0
    OS << "<condcode " << getCondCode() << ">";
1814
0
    break;
1815
0
  case k_Register:
1816
0
    OS << "<register " << getReg() << ">";
1817
0
    break;
1818
0
  case k_VectorList: {
1819
0
    OS << "<vectorlist ";
1820
0
    unsigned Reg = getVectorListStart();
1821
0
    for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1822
0
      OS << Reg + i << " ";
1823
0
    OS << ">";
1824
0
    break;
1825
0
  }
1826
0
  case k_VectorIndex:
1827
0
    OS << "<vectorindex " << getVectorIndex() << ">";
1828
0
    break;
1829
0
  case k_SysReg:
1830
0
    OS << "<sysreg: " << getSysReg() << '>';
1831
0
    break;
1832
0
  case k_Token:
1833
0
    OS << "'" << getToken() << "'";
1834
0
    break;
1835
0
  case k_SysCR:
1836
0
    OS << "c" << getSysCR();
1837
0
    break;
1838
0
  case k_Prefetch: {
1839
0
    StringRef Name = getPrefetchName();
1840
0
    if (!Name.empty())
1841
0
      OS << "<prfop " << Name << ">";
1842
0
    else
1843
0
      OS << "<prfop invalid #" << getPrefetch() << ">";
1844
0
    break;
1845
0
  }
1846
0
  case k_PSBHint: {
1847
0
    OS << getPSBHintName();
1848
0
    break;
1849
0
  }
1850
0
  case k_ShiftExtend: {
1851
0
    OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1852
0
       << getShiftExtendAmount();
1853
0
    if (!hasShiftExtendAmount())
1854
0
      OS << "<imp>";
1855
0
    OS << '>';
1856
0
    break;
1857
0
  }
1858
0
  }
1859
0
}
1860
1861
/// @name Auto-generated Match Functions
1862
/// {
1863
1864
static unsigned MatchRegisterName(StringRef Name);
1865
1866
/// }
1867
1868
25.7k
static unsigned matchVectorRegName(StringRef Name) {
1869
25.7k
  return StringSwitch<unsigned>(Name.lower())
1870
25.7k
      .Case("v0", AArch64::Q0)
1871
25.7k
      .Case("v1", AArch64::Q1)
1872
25.7k
      .Case("v2", AArch64::Q2)
1873
25.7k
      .Case("v3", AArch64::Q3)
1874
25.7k
      .Case("v4", AArch64::Q4)
1875
25.7k
      .Case("v5", AArch64::Q5)
1876
25.7k
      .Case("v6", AArch64::Q6)
1877
25.7k
      .Case("v7", AArch64::Q7)
1878
25.7k
      .Case("v8", AArch64::Q8)
1879
25.7k
      .Case("v9", AArch64::Q9)
1880
25.7k
      .Case("v10", AArch64::Q10)
1881
25.7k
      .Case("v11", AArch64::Q11)
1882
25.7k
      .Case("v12", AArch64::Q12)
1883
25.7k
      .Case("v13", AArch64::Q13)
1884
25.7k
      .Case("v14", AArch64::Q14)
1885
25.7k
      .Case("v15", AArch64::Q15)
1886
25.7k
      .Case("v16", AArch64::Q16)
1887
25.7k
      .Case("v17", AArch64::Q17)
1888
25.7k
      .Case("v18", AArch64::Q18)
1889
25.7k
      .Case("v19", AArch64::Q19)
1890
25.7k
      .Case("v20", AArch64::Q20)
1891
25.7k
      .Case("v21", AArch64::Q21)
1892
25.7k
      .Case("v22", AArch64::Q22)
1893
25.7k
      .Case("v23", AArch64::Q23)
1894
25.7k
      .Case("v24", AArch64::Q24)
1895
25.7k
      .Case("v25", AArch64::Q25)
1896
25.7k
      .Case("v26", AArch64::Q26)
1897
25.7k
      .Case("v27", AArch64::Q27)
1898
25.7k
      .Case("v28", AArch64::Q28)
1899
25.7k
      .Case("v29", AArch64::Q29)
1900
25.7k
      .Case("v30", AArch64::Q30)
1901
25.7k
      .Case("v31", AArch64::Q31)
1902
25.7k
      .Default(0);
1903
25.7k
}
1904
1905
4.37k
static bool isValidVectorKind(StringRef Name) {
1906
4.37k
  return StringSwitch<bool>(Name.lower())
1907
4.37k
      .Case(".8b", true)
1908
4.37k
      .Case(".16b", true)
1909
4.37k
      .Case(".4h", true)
1910
4.37k
      .Case(".8h", true)
1911
4.37k
      .Case(".2s", true)
1912
4.37k
      .Case(".4s", true)
1913
4.37k
      .Case(".1d", true)
1914
4.37k
      .Case(".2d", true)
1915
4.37k
      .Case(".1q", true)
1916
      // Accept the width neutral ones, too, for verbose syntax. If those
1917
      // aren't used in the right places, the token operand won't match so
1918
      // all will work out.
1919
4.37k
      .Case(".b", true)
1920
4.37k
      .Case(".h", true)
1921
4.37k
      .Case(".s", true)
1922
4.37k
      .Case(".d", true)
1923
      // Needed for fp16 scalar pairwise reductions
1924
4.37k
      .Case(".2h", true)
1925
4.37k
      .Default(false);
1926
4.37k
}
1927
1928
static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
1929
0
                                 char &ElementKind) {
1930
0
  assert(isValidVectorKind(Name));
1931
1932
0
  ElementKind = Name.lower()[Name.size() - 1];
1933
0
  NumElements = 0;
1934
1935
0
  if (Name.size() == 2)
1936
0
    return;
1937
1938
  // Parse the lane count
1939
0
  Name = Name.drop_front();
1940
0
  while (isdigit(Name.front())) {
1941
0
    NumElements = 10 * NumElements + (Name.front() - '0');
1942
0
    Name = Name.drop_front();
1943
0
  }
1944
0
}
1945
1946
bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1947
0
                                     SMLoc &EndLoc, unsigned int &ErrorCode) {
1948
0
  StartLoc = getLoc();
1949
0
  RegNo = tryParseRegister();
1950
0
  EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1951
0
  return (RegNo == (unsigned)-1);
1952
0
}
1953
1954
// Matches a register name or register alias previously defined by '.req'
1955
unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
1956
49.6k
                                                  bool isVector) {
1957
49.6k
  unsigned RegNum = isVector ? matchVectorRegName(Name)
1958
49.6k
                             : MatchRegisterName(Name);
1959
1960
49.6k
  if (RegNum == 0) {
1961
    // Check for aliases registered via .req. Canonicalize to lower case.
1962
    // That's more consistent since register names are case insensitive, and
1963
    // it's how the original entry was passed in from MC/MCParser/AsmParser.
1964
41.7k
    auto Entry = RegisterReqs.find(Name.lower());
1965
41.7k
    if (Entry == RegisterReqs.end())
1966
41.7k
      return 0;
1967
    // set RegNum if the match is the right kind of register
1968
0
    if (isVector == Entry->getValue().first)
1969
0
      RegNum = Entry->getValue().second;
1970
0
  }
1971
7.89k
  return RegNum;
1972
49.6k
}
1973
1974
/// tryParseRegister - Try to parse a register name. The token must be an
1975
/// Identifier when called, and if it is a register name the token is eaten and
1976
/// the register is added to the operand list.
1977
23.7k
int AArch64AsmParser::tryParseRegister() {
1978
23.7k
  MCAsmParser &Parser = getParser();
1979
23.7k
  const AsmToken &Tok = Parser.getTok();
1980
23.7k
  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1981
1982
23.7k
  std::string lowerCase = Tok.getString().lower();
1983
23.7k
  unsigned RegNum = matchRegisterNameAlias(lowerCase, false);
1984
  // Also handle a few aliases of registers.
1985
23.7k
  if (RegNum == 0)
1986
20.9k
    RegNum = StringSwitch<unsigned>(lowerCase)
1987
20.9k
                 .Case("fp",  AArch64::FP)
1988
20.9k
                 .Case("lr",  AArch64::LR)
1989
20.9k
                 .Case("x31", AArch64::XZR)
1990
20.9k
                 .Case("w31", AArch64::WZR)
1991
20.9k
                 .Default(0);
1992
1993
23.7k
  if (RegNum == 0)
1994
20.0k
    return -1;
1995
1996
3.69k
  Parser.Lex(); // Eat identifier token.
1997
3.69k
  return RegNum;
1998
23.7k
}
1999
2000
/// tryMatchVectorRegister - Try to parse a vector register name with optional
2001
/// kind specifier. If it is a register specifier, eat the token and return it.
2002
int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected)
2003
25.7k
{
2004
25.7k
  MCAsmParser &Parser = getParser();
2005
25.7k
  if (Parser.getTok().isNot(AsmToken::Identifier)) {
2006
    //TokError("vector register expected");
2007
4
    return -1;
2008
4
  }
2009
2010
25.7k
  StringRef Name = Parser.getTok().getString();
2011
  // If there is a kind specifier, it's separated from the register name by
2012
  // a '.'.
2013
25.7k
  size_t Start = 0, Next = Name.find('.');
2014
25.7k
  StringRef Head = Name.slice(Start, Next);
2015
25.7k
  unsigned RegNum = matchRegisterNameAlias(Head, true);
2016
2017
25.7k
  if (RegNum) {
2018
5.09k
    if (Next != StringRef::npos) {
2019
4.37k
      Kind = Name.slice(Next, StringRef::npos);
2020
4.37k
      if (!isValidVectorKind(Kind)) {
2021
        //TokError("invalid vector kind qualifier");
2022
3.11k
        return -1;
2023
3.11k
      }
2024
4.37k
    }
2025
1.98k
    Parser.Lex(); // Eat the register token.
2026
1.98k
    return RegNum;
2027
5.09k
  }
2028
2029
  //if (expected)
2030
  //  TokError("vector register expected");
2031
20.6k
  return -1;
2032
25.7k
}
2033
2034
/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
2035
AArch64AsmParser::OperandMatchResultTy
2036
AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands)
2037
2
{
2038
2
  MCAsmParser &Parser = getParser();
2039
2
  SMLoc S = getLoc();
2040
2041
2
  if (Parser.getTok().isNot(AsmToken::Identifier)) {
2042
    //Error(S, "Expected cN operand where 0 <= N <= 15");
2043
0
    return MatchOperand_ParseFail;
2044
0
  }
2045
2046
2
  StringRef Tok = Parser.getTok().getIdentifier();
2047
2
  if (Tok[0] != 'c' && Tok[0] != 'C') {
2048
    //Error(S, "Expected cN operand where 0 <= N <= 15");
2049
0
    return MatchOperand_ParseFail;
2050
0
  }
2051
2052
2
  uint32_t CRNum;
2053
2
  bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2054
2
  if (BadNum || CRNum > 15) {
2055
    //Error(S, "Expected cN operand where 0 <= N <= 15");
2056
2
    return MatchOperand_ParseFail;
2057
2
  }
2058
2059
0
  Parser.Lex(); // Eat identifier token.
2060
0
  Operands.push_back(
2061
0
      AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2062
0
  return MatchOperand_Success;
2063
2
}
2064
2065
/// tryParsePrefetch - Try to parse a prefetch operand.
2066
AArch64AsmParser::OperandMatchResultTy
2067
5
AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
2068
5
  MCAsmParser &Parser = getParser();
2069
5
  SMLoc S = getLoc();
2070
5
  const AsmToken &Tok = Parser.getTok();
2071
  // Either an identifier for named values or a 5-bit immediate.
2072
5
  bool Hash = Tok.is(AsmToken::Hash);
2073
5
  if (Hash || Tok.is(AsmToken::Integer)) {
2074
5
    if (Hash)
2075
5
      Parser.Lex(); // Eat hash token.
2076
5
    const MCExpr *ImmVal;
2077
5
    if (getParser().parseExpression(ImmVal))
2078
4
      return MatchOperand_ParseFail;
2079
2080
1
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2081
1
    if (!MCE) {
2082
      //TokError("immediate value expected for prefetch operand");
2083
0
      return MatchOperand_ParseFail;
2084
0
    }
2085
1
    unsigned prfop = MCE->getValue();
2086
1
    if (prfop > 31) {
2087
      //TokError("prefetch operand out of range, [0,31] expected");
2088
1
      return MatchOperand_ParseFail;
2089
1
    }
2090
2091
0
    bool Valid;
2092
0
    auto Mapper = AArch64PRFM::PRFMMapper();
2093
0
    StringRef Name = 
2094
0
        Mapper.toString(MCE->getValue(), getSTI().getFeatureBits(), Valid);
2095
0
    Operands.push_back(AArch64Operand::CreatePrefetch(prfop, Name,
2096
0
                                                      S, getContext()));
2097
0
    return MatchOperand_Success;
2098
1
  }
2099
2100
0
  if (Tok.isNot(AsmToken::Identifier)) {
2101
    //TokError("pre-fetch hint expected");
2102
0
    return MatchOperand_ParseFail;
2103
0
  }
2104
2105
0
  bool Valid;
2106
0
  auto Mapper = AArch64PRFM::PRFMMapper();
2107
0
  unsigned prfop = 
2108
0
      Mapper.fromString(Tok.getString(), getSTI().getFeatureBits(), Valid);
2109
0
  if (!Valid) {
2110
    //TokError("pre-fetch hint expected");
2111
0
    return MatchOperand_ParseFail;
2112
0
  }
2113
2114
0
  Parser.Lex(); // Eat identifier token.
2115
0
  Operands.push_back(AArch64Operand::CreatePrefetch(prfop, Tok.getString(),
2116
0
                                                    S, getContext()));
2117
0
  return MatchOperand_Success;
2118
0
}
2119
2120
/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
2121
AArch64AsmParser::OperandMatchResultTy
2122
0
AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2123
0
  MCAsmParser &Parser = getParser();
2124
0
  SMLoc S = getLoc();
2125
0
  const AsmToken &Tok = Parser.getTok();
2126
0
  if (Tok.isNot(AsmToken::Identifier)) {
2127
    //TokError("invalid operand for instruction");
2128
0
    return MatchOperand_ParseFail;
2129
0
  }
2130
2131
0
  bool Valid;
2132
0
  auto Mapper = AArch64PSBHint::PSBHintMapper();
2133
0
  unsigned psbhint =
2134
0
      Mapper.fromString(Tok.getString(), getSTI().getFeatureBits(), Valid);
2135
0
  if (!Valid) {
2136
    //TokError("invalid operand for instruction");
2137
0
    return MatchOperand_ParseFail;
2138
0
  }
2139
2140
0
  Parser.Lex(); // Eat identifier token.
2141
0
  Operands.push_back(AArch64Operand::CreatePSBHint(psbhint, Tok.getString(),
2142
0
                                                   S, getContext()));
2143
0
  return MatchOperand_Success;
2144
0
}
2145
2146
/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2147
/// instruction.
2148
AArch64AsmParser::OperandMatchResultTy
2149
3
AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
2150
3
  MCAsmParser &Parser = getParser();
2151
3
  SMLoc S = getLoc();
2152
3
  const MCExpr *Expr;
2153
2154
3
  if (Parser.getTok().is(AsmToken::Hash)) {
2155
0
    Parser.Lex(); // Eat hash token.
2156
0
  }
2157
2158
3
  if (parseSymbolicImmVal(Expr))
2159
0
    return MatchOperand_ParseFail;
2160
2161
3
  AArch64MCExpr::VariantKind ELFRefKind;
2162
3
  MCSymbolRefExpr::VariantKind DarwinRefKind;
2163
3
  int64_t Addend;
2164
3
  if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2165
1
    if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2166
1
        ELFRefKind == AArch64MCExpr::VK_INVALID) {
2167
      // No modifier was specified at all; this is the syntax for an ELF basic
2168
      // ADRP relocation (unfortunately).
2169
1
      Expr =
2170
1
          AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
2171
1
    } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2172
0
                DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2173
0
               Addend != 0) {
2174
      //Error(S, "gotpage label reference not allowed an addend");
2175
0
      return MatchOperand_ParseFail;
2176
0
    } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2177
0
               DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2178
0
               DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2179
0
               ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2180
0
               ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2181
0
               ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2182
      // The operand must be an @page or @gotpage qualified symbolref.
2183
      //Error(S, "page or gotpage label reference expected");
2184
0
      return MatchOperand_ParseFail;
2185
0
    }
2186
1
  }
2187
2188
  // We have either a label reference possibly with addend or an immediate. The
2189
  // addend is a raw value here. The linker will adjust it to only reference the
2190
  // page.
2191
3
  SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2192
3
  Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2193
2194
3
  return MatchOperand_Success;
2195
3
}
2196
2197
/// tryParseAdrLabel - Parse and validate a source label for the ADR
2198
/// instruction.
2199
AArch64AsmParser::OperandMatchResultTy
2200
345
AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2201
345
  MCAsmParser &Parser = getParser();
2202
345
  SMLoc S = getLoc();
2203
345
  const MCExpr *Expr;
2204
2205
345
  if (Parser.getTok().is(AsmToken::Hash)) {
2206
345
    Parser.Lex(); // Eat hash token.
2207
345
  }
2208
2209
345
  if (getParser().parseExpression(Expr))
2210
345
    return MatchOperand_ParseFail;
2211
2212
0
  SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2213
0
  Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2214
2215
0
  return MatchOperand_Success;
2216
345
}
2217
2218
/// tryParseFPImm - A floating point immediate expression operand.
2219
AArch64AsmParser::OperandMatchResultTy
2220
621
AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
2221
621
  MCAsmParser &Parser = getParser();
2222
621
  SMLoc S = getLoc();
2223
2224
621
  bool Hash = false;
2225
621
  if (Parser.getTok().is(AsmToken::Hash)) {
2226
0
    Parser.Lex(); // Eat '#'
2227
0
    Hash = true;
2228
0
  }
2229
2230
  // Handle negation, as that still comes through as a separate token.
2231
621
  bool isNegative = false;
2232
621
  if (Parser.getTok().is(AsmToken::Minus)) {
2233
291
    isNegative = true;
2234
291
    Parser.Lex();
2235
291
  }
2236
621
  const AsmToken &Tok = Parser.getTok();
2237
621
  if (Tok.is(AsmToken::Real)) {
2238
0
    APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
2239
0
    if (isNegative)
2240
0
      RealVal.changeSign();
2241
2242
0
    if (RealVal.bitcastToAPInt().getActiveBits() > 64)
2243
0
        return MatchOperand_ParseFail;
2244
0
    uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2245
0
    int Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2246
0
    Parser.Lex(); // Eat the token.
2247
    // Check for out of range values. As an exception, we let Zero through,
2248
    // as we handle that special case in post-processing before matching in
2249
    // order to use the zero register for it.
2250
0
    if (Val == -1 && !RealVal.isPosZero()) {
2251
      //TokError("expected compatible register or floating-point constant");
2252
0
      return MatchOperand_ParseFail;
2253
0
    }
2254
0
    Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2255
0
    return MatchOperand_Success;
2256
0
  }
2257
621
  if (Tok.is(AsmToken::Integer)) {
2258
1
    int64_t Val;
2259
1
    if (!isNegative && Tok.getString().startswith("0x")) {
2260
0
      bool valid;
2261
0
      Val = Tok.getIntVal(valid);
2262
0
      if (!valid)
2263
0
        return MatchOperand_ParseFail;
2264
0
      if (Val > 255 || Val < 0) {
2265
        //TokError("encoded floating point value out of range");
2266
0
        return MatchOperand_ParseFail;
2267
0
      }
2268
1
    } else {
2269
1
      APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
2270
1
      if (RealVal.bitcastToAPInt().getActiveBits() > 64)
2271
0
          return MatchOperand_ParseFail;
2272
1
      uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
2273
      // If we had a '-' in front, toggle the sign bit.
2274
1
      IntVal ^= (uint64_t)isNegative << 63;
2275
1
      Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
2276
1
    }
2277
1
    Parser.Lex(); // Eat the token.
2278
1
    Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2279
1
    return MatchOperand_Success;
2280
1
  }
2281
2282
620
  if (!Hash)
2283
620
    return MatchOperand_NoMatch;
2284
2285
  //TokError("invalid floating point immediate");
2286
0
  return MatchOperand_ParseFail;
2287
620
}
2288
2289
/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
2290
AArch64AsmParser::OperandMatchResultTy
2291
260
AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
2292
260
  MCAsmParser &Parser = getParser();
2293
260
  SMLoc S = getLoc();
2294
2295
260
  if (Parser.getTok().is(AsmToken::Hash))
2296
8
    Parser.Lex(); // Eat '#'
2297
252
  else if (Parser.getTok().isNot(AsmToken::Integer))
2298
    // Operand should start from # or should be integer, emit error otherwise.
2299
240
    return MatchOperand_NoMatch;
2300
2301
20
  const MCExpr *Imm;
2302
20
  if (parseSymbolicImmVal(Imm))
2303
8
    return MatchOperand_ParseFail;
2304
12
  else if (Parser.getTok().isNot(AsmToken::Comma)) {
2305
12
    uint64_t ShiftAmount = 0;
2306
12
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2307
12
    if (MCE) {
2308
12
      int64_t Val = MCE->getValue();
2309
12
      if (Val > 0xfff && (Val & 0xfff) == 0) {
2310
0
        Imm = MCConstantExpr::create(Val >> 12, getContext());
2311
0
        ShiftAmount = 12;
2312
0
      }
2313
12
    }
2314
12
    SMLoc E = Parser.getTok().getLoc();
2315
12
    Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2316
12
                                                        getContext()));
2317
12
    return MatchOperand_Success;
2318
12
  }
2319
2320
  // Eat ','
2321
0
  Parser.Lex();
2322
2323
  // The optional operand must be "lsl #N" where N is non-negative.
2324
0
  if (!Parser.getTok().is(AsmToken::Identifier) ||
2325
0
      !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2326
    //Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2327
0
    return MatchOperand_ParseFail;
2328
0
  }
2329
2330
  // Eat 'lsl'
2331
0
  Parser.Lex();
2332
2333
0
  if (Parser.getTok().is(AsmToken::Hash)) {
2334
0
    Parser.Lex();
2335
0
  }
2336
2337
0
  if (Parser.getTok().isNot(AsmToken::Integer)) {
2338
    //Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2339
0
    return MatchOperand_ParseFail;
2340
0
  }
2341
2342
0
  bool valid;
2343
0
  int64_t ShiftAmount = Parser.getTok().getIntVal(valid);
2344
0
  if (!valid)
2345
0
    return MatchOperand_ParseFail;
2346
2347
0
  if (ShiftAmount < 0) {
2348
    //Error(Parser.getTok().getLoc(), "positive shift amount required");
2349
0
    return MatchOperand_ParseFail;
2350
0
  }
2351
0
  Parser.Lex(); // Eat the number
2352
2353
0
  SMLoc E = Parser.getTok().getLoc();
2354
0
  Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2355
0
                                                      S, E, getContext()));
2356
0
  return MatchOperand_Success;
2357
0
}
2358
2359
/// parseCondCodeString - Parse a Condition Code string.
2360
490
AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2361
490
  AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2362
490
                    .Case("eq", AArch64CC::EQ)
2363
490
                    .Case("ne", AArch64CC::NE)
2364
490
                    .Case("cs", AArch64CC::HS)
2365
490
                    .Case("hs", AArch64CC::HS)
2366
490
                    .Case("cc", AArch64CC::LO)
2367
490
                    .Case("lo", AArch64CC::LO)
2368
490
                    .Case("mi", AArch64CC::MI)
2369
490
                    .Case("pl", AArch64CC::PL)
2370
490
                    .Case("vs", AArch64CC::VS)
2371
490
                    .Case("vc", AArch64CC::VC)
2372
490
                    .Case("hi", AArch64CC::HI)
2373
490
                    .Case("ls", AArch64CC::LS)
2374
490
                    .Case("ge", AArch64CC::GE)
2375
490
                    .Case("lt", AArch64CC::LT)
2376
490
                    .Case("gt", AArch64CC::GT)
2377
490
                    .Case("le", AArch64CC::LE)
2378
490
                    .Case("al", AArch64CC::AL)
2379
490
                    .Case("nv", AArch64CC::NV)
2380
490
                    .Default(AArch64CC::Invalid);
2381
490
  return CC;
2382
490
}
2383
2384
/// parseCondCode - Parse a Condition Code operand.
2385
bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2386
0
                                     bool invertCondCode) {
2387
0
  MCAsmParser &Parser = getParser();
2388
0
  SMLoc S = getLoc();
2389
0
  const AsmToken &Tok = Parser.getTok();
2390
0
  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2391
2392
0
  StringRef Cond = Tok.getString();
2393
0
  AArch64CC::CondCode CC = parseCondCodeString(Cond);
2394
0
  if (CC == AArch64CC::Invalid)
2395
    //return TokError("invalid condition code");
2396
0
    return true;
2397
0
  Parser.Lex(); // Eat identifier token.
2398
2399
0
  if (invertCondCode) {
2400
0
    if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2401
      //return TokError("condition codes AL and NV are invalid for this instruction");
2402
0
      return true;
2403
0
    CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
2404
0
  }
2405
2406
0
  Operands.push_back(
2407
0
      AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2408
0
  return false;
2409
0
}
2410
2411
/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2412
/// them if present.
2413
AArch64AsmParser::OperandMatchResultTy
2414
20.0k
AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
2415
20.0k
  MCAsmParser &Parser = getParser();
2416
20.0k
  const AsmToken &Tok = Parser.getTok();
2417
20.0k
  std::string LowerID = Tok.getString().lower();
2418
20.0k
  AArch64_AM::ShiftExtendType ShOp =
2419
20.0k
      StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2420
20.0k
          .Case("lsl", AArch64_AM::LSL)
2421
20.0k
          .Case("lsr", AArch64_AM::LSR)
2422
20.0k
          .Case("asr", AArch64_AM::ASR)
2423
20.0k
          .Case("ror", AArch64_AM::ROR)
2424
20.0k
          .Case("msl", AArch64_AM::MSL)
2425
20.0k
          .Case("uxtb", AArch64_AM::UXTB)
2426
20.0k
          .Case("uxth", AArch64_AM::UXTH)
2427
20.0k
          .Case("uxtw", AArch64_AM::UXTW)
2428
20.0k
          .Case("uxtx", AArch64_AM::UXTX)
2429
20.0k
          .Case("sxtb", AArch64_AM::SXTB)
2430
20.0k
          .Case("sxth", AArch64_AM::SXTH)
2431
20.0k
          .Case("sxtw", AArch64_AM::SXTW)
2432
20.0k
          .Case("sxtx", AArch64_AM::SXTX)
2433
20.0k
          .Default(AArch64_AM::InvalidShiftExtend);
2434
2435
20.0k
  if (ShOp == AArch64_AM::InvalidShiftExtend)
2436
19.9k
    return MatchOperand_NoMatch;
2437
2438
78
  SMLoc S = Tok.getLoc();
2439
78
  Parser.Lex();
2440
2441
78
  bool Hash = getLexer().is(AsmToken::Hash);
2442
78
  if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2443
78
    if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2444
78
        ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2445
78
        ShOp == AArch64_AM::MSL) {
2446
      // We expect a number here.
2447
      //TokError("expected #imm after shift specifier");
2448
0
      return MatchOperand_ParseFail;
2449
0
    }
2450
2451
    // "extend" type operatoins don't need an immediate, #0 is implicit.
2452
78
    SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2453
78
    Operands.push_back(
2454
78
        AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2455
78
    return MatchOperand_Success;
2456
78
  }
2457
2458
0
  if (Hash)
2459
0
    Parser.Lex(); // Eat the '#'.
2460
2461
  // Make sure we do actually have a number or a parenthesized expression.
2462
0
  SMLoc E = Parser.getTok().getLoc();
2463
0
  if (!Parser.getTok().is(AsmToken::Integer) &&
2464
0
      !Parser.getTok().is(AsmToken::LParen)) {
2465
    //Error(E, "expected integer shift amount");
2466
0
    return MatchOperand_ParseFail;
2467
0
  }
2468
2469
0
  const MCExpr *ImmVal;
2470
0
  if (getParser().parseExpression(ImmVal))
2471
0
    return MatchOperand_ParseFail;
2472
2473
0
  const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2474
0
  if (!MCE) {
2475
    //Error(E, "expected constant '#imm' after shift specifier");
2476
0
    return MatchOperand_ParseFail;
2477
0
  }
2478
2479
0
  E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2480
0
  Operands.push_back(AArch64Operand::CreateShiftExtend(
2481
0
      ShOp, MCE->getValue(), true, S, E, getContext()));
2482
0
  return MatchOperand_Success;
2483
0
}
2484
2485
/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2486
/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2487
bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2488
                                   OperandVector &Operands)
2489
1
{
2490
1
  if (Name.find('.') != StringRef::npos)
2491
    //return TokError("invalid operand");
2492
0
    return true;
2493
2494
1
  Mnemonic = Name;
2495
1
  Operands.push_back(
2496
1
      AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2497
2498
1
  MCAsmParser &Parser = getParser();
2499
1
  const AsmToken &Tok = Parser.getTok();
2500
1
  StringRef Op = Tok.getString();
2501
1
  SMLoc S = Tok.getLoc();
2502
2503
1
  const MCExpr *Expr = nullptr;
2504
2505
1
#define SYS_ALIAS(op1, Cn, Cm, op2)                                            \
2506
1
  do {                                                                         \
2507
0
    Expr = MCConstantExpr::create(op1, getContext());                          \
2508
0
    Operands.push_back(                                                        \
2509
0
        AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));           \
2510
0
    Operands.push_back(                                                        \
2511
0
        AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));           \
2512
0
    Operands.push_back(                                                        \
2513
0
        AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));           \
2514
0
    Expr = MCConstantExpr::create(op2, getContext());                          \
2515
0
    Operands.push_back(                                                        \
2516
0
        AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));           \
2517
0
  } while (0)
2518
2519
1
  if (Mnemonic == "ic") {
2520
0
    if (!Op.compare_lower("ialluis")) {
2521
      // SYS #0, C7, C1, #0
2522
0
      SYS_ALIAS(0, 7, 1, 0);
2523
0
    } else if (!Op.compare_lower("iallu")) {
2524
      // SYS #0, C7, C5, #0
2525
0
      SYS_ALIAS(0, 7, 5, 0);
2526
0
    } else if (!Op.compare_lower("ivau")) {
2527
      // SYS #3, C7, C5, #1
2528
0
      SYS_ALIAS(3, 7, 5, 1);
2529
0
    } else {
2530
      //return TokError("invalid operand for IC instruction");
2531
0
      return true;
2532
0
    }
2533
1
  } else if (Mnemonic == "dc") {
2534
1
    if (!Op.compare_lower("zva")) {
2535
      // SYS #3, C7, C4, #1
2536
0
      SYS_ALIAS(3, 7, 4, 1);
2537
1
    } else if (!Op.compare_lower("ivac")) {
2538
      // SYS #3, C7, C6, #1
2539
0
      SYS_ALIAS(0, 7, 6, 1);
2540
1
    } else if (!Op.compare_lower("isw")) {
2541
      // SYS #0, C7, C6, #2
2542
0
      SYS_ALIAS(0, 7, 6, 2);
2543
1
    } else if (!Op.compare_lower("cvac")) {
2544
      // SYS #3, C7, C10, #1
2545
0
      SYS_ALIAS(3, 7, 10, 1);
2546
1
    } else if (!Op.compare_lower("csw")) {
2547
      // SYS #0, C7, C10, #2
2548
0
      SYS_ALIAS(0, 7, 10, 2);
2549
1
    } else if (!Op.compare_lower("cvau")) {
2550
      // SYS #3, C7, C11, #1
2551
0
      SYS_ALIAS(3, 7, 11, 1);
2552
1
    } else if (!Op.compare_lower("civac")) {
2553
      // SYS #3, C7, C14, #1
2554
0
      SYS_ALIAS(3, 7, 14, 1);
2555
1
    } else if (!Op.compare_lower("cisw")) {
2556
      // SYS #0, C7, C14, #2
2557
0
      SYS_ALIAS(0, 7, 14, 2);
2558
1
    } else if (!Op.compare_lower("cvap")) {
2559
0
      if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2560
        // SYS #3, C7, C12, #1
2561
0
        SYS_ALIAS(3, 7, 12, 1);
2562
0
      } else {
2563
        //return TokError("DC CVAP requires ARMv8.2a");
2564
0
        return true;
2565
0
      }
2566
1
    } else {
2567
      //return TokError("invalid operand for DC instruction");
2568
1
      return true;
2569
1
    }
2570
1
  } else if (Mnemonic == "at") {
2571
0
    if (!Op.compare_lower("s1e1r")) {
2572
      // SYS #0, C7, C8, #0
2573
0
      SYS_ALIAS(0, 7, 8, 0);
2574
0
    } else if (!Op.compare_lower("s1e2r")) {
2575
      // SYS #4, C7, C8, #0
2576
0
      SYS_ALIAS(4, 7, 8, 0);
2577
0
    } else if (!Op.compare_lower("s1e3r")) {
2578
      // SYS #6, C7, C8, #0
2579
0
      SYS_ALIAS(6, 7, 8, 0);
2580
0
    } else if (!Op.compare_lower("s1e1w")) {
2581
      // SYS #0, C7, C8, #1
2582
0
      SYS_ALIAS(0, 7, 8, 1);
2583
0
    } else if (!Op.compare_lower("s1e2w")) {
2584
      // SYS #4, C7, C8, #1
2585
0
      SYS_ALIAS(4, 7, 8, 1);
2586
0
    } else if (!Op.compare_lower("s1e3w")) {
2587
      // SYS #6, C7, C8, #1
2588
0
      SYS_ALIAS(6, 7, 8, 1);
2589
0
    } else if (!Op.compare_lower("s1e0r")) {
2590
      // SYS #0, C7, C8, #3
2591
0
      SYS_ALIAS(0, 7, 8, 2);
2592
0
    } else if (!Op.compare_lower("s1e0w")) {
2593
      // SYS #0, C7, C8, #3
2594
0
      SYS_ALIAS(0, 7, 8, 3);
2595
0
    } else if (!Op.compare_lower("s12e1r")) {
2596
      // SYS #4, C7, C8, #4
2597
0
      SYS_ALIAS(4, 7, 8, 4);
2598
0
    } else if (!Op.compare_lower("s12e1w")) {
2599
      // SYS #4, C7, C8, #5
2600
0
      SYS_ALIAS(4, 7, 8, 5);
2601
0
    } else if (!Op.compare_lower("s12e0r")) {
2602
      // SYS #4, C7, C8, #6
2603
0
      SYS_ALIAS(4, 7, 8, 6);
2604
0
    } else if (!Op.compare_lower("s12e0w")) {
2605
      // SYS #4, C7, C8, #7
2606
0
      SYS_ALIAS(4, 7, 8, 7);
2607
0
    } else if (!Op.compare_lower("s1e1rp")) {
2608
0
      if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2609
        // SYS #0, C7, C9, #0
2610
0
        SYS_ALIAS(0, 7, 9, 0);
2611
0
      } else {
2612
        //return TokError("AT S1E1RP requires ARMv8.2a");
2613
0
        return true;
2614
0
      }
2615
0
    } else if (!Op.compare_lower("s1e1wp")) {
2616
0
      if (getSTI().getFeatureBits()[AArch64::HasV8_2aOps]) {
2617
        // SYS #0, C7, C9, #1
2618
0
        SYS_ALIAS(0, 7, 9, 1);
2619
0
      } else {
2620
        //return TokError("AT S1E1WP requires ARMv8.2a");
2621
0
        return true;
2622
0
      }
2623
0
    } else {
2624
      //return TokError("invalid operand for AT instruction");
2625
0
      return true;
2626
0
    }
2627
0
  } else if (Mnemonic == "tlbi") {
2628
0
    if (!Op.compare_lower("vmalle1is")) {
2629
      // SYS #0, C8, C3, #0
2630
0
      SYS_ALIAS(0, 8, 3, 0);
2631
0
    } else if (!Op.compare_lower("alle2is")) {
2632
      // SYS #4, C8, C3, #0
2633
0
      SYS_ALIAS(4, 8, 3, 0);
2634
0
    } else if (!Op.compare_lower("alle3is")) {
2635
      // SYS #6, C8, C3, #0
2636
0
      SYS_ALIAS(6, 8, 3, 0);
2637
0
    } else if (!Op.compare_lower("vae1is")) {
2638
      // SYS #0, C8, C3, #1
2639
0
      SYS_ALIAS(0, 8, 3, 1);
2640
0
    } else if (!Op.compare_lower("vae2is")) {
2641
      // SYS #4, C8, C3, #1
2642
0
      SYS_ALIAS(4, 8, 3, 1);
2643
0
    } else if (!Op.compare_lower("vae3is")) {
2644
      // SYS #6, C8, C3, #1
2645
0
      SYS_ALIAS(6, 8, 3, 1);
2646
0
    } else if (!Op.compare_lower("aside1is")) {
2647
      // SYS #0, C8, C3, #2
2648
0
      SYS_ALIAS(0, 8, 3, 2);
2649
0
    } else if (!Op.compare_lower("vaae1is")) {
2650
      // SYS #0, C8, C3, #3
2651
0
      SYS_ALIAS(0, 8, 3, 3);
2652
0
    } else if (!Op.compare_lower("alle1is")) {
2653
      // SYS #4, C8, C3, #4
2654
0
      SYS_ALIAS(4, 8, 3, 4);
2655
0
    } else if (!Op.compare_lower("vale1is")) {
2656
      // SYS #0, C8, C3, #5
2657
0
      SYS_ALIAS(0, 8, 3, 5);
2658
0
    } else if (!Op.compare_lower("vaale1is")) {
2659
      // SYS #0, C8, C3, #7
2660
0
      SYS_ALIAS(0, 8, 3, 7);
2661
0
    } else if (!Op.compare_lower("vmalle1")) {
2662
      // SYS #0, C8, C7, #0
2663
0
      SYS_ALIAS(0, 8, 7, 0);
2664
0
    } else if (!Op.compare_lower("alle2")) {
2665
      // SYS #4, C8, C7, #0
2666
0
      SYS_ALIAS(4, 8, 7, 0);
2667
0
    } else if (!Op.compare_lower("vale2is")) {
2668
      // SYS #4, C8, C3, #5
2669
0
      SYS_ALIAS(4, 8, 3, 5);
2670
0
    } else if (!Op.compare_lower("vale3is")) {
2671
      // SYS #6, C8, C3, #5
2672
0
      SYS_ALIAS(6, 8, 3, 5);
2673
0
    } else if (!Op.compare_lower("alle3")) {
2674
      // SYS #6, C8, C7, #0
2675
0
      SYS_ALIAS(6, 8, 7, 0);
2676
0
    } else if (!Op.compare_lower("vae1")) {
2677
      // SYS #0, C8, C7, #1
2678
0
      SYS_ALIAS(0, 8, 7, 1);
2679
0
    } else if (!Op.compare_lower("vae2")) {
2680
      // SYS #4, C8, C7, #1
2681
0
      SYS_ALIAS(4, 8, 7, 1);
2682
0
    } else if (!Op.compare_lower("vae3")) {
2683
      // SYS #6, C8, C7, #1
2684
0
      SYS_ALIAS(6, 8, 7, 1);
2685
0
    } else if (!Op.compare_lower("aside1")) {
2686
      // SYS #0, C8, C7, #2
2687
0
      SYS_ALIAS(0, 8, 7, 2);
2688
0
    } else if (!Op.compare_lower("vaae1")) {
2689
      // SYS #0, C8, C7, #3
2690
0
      SYS_ALIAS(0, 8, 7, 3);
2691
0
    } else if (!Op.compare_lower("alle1")) {
2692
      // SYS #4, C8, C7, #4
2693
0
      SYS_ALIAS(4, 8, 7, 4);
2694
0
    } else if (!Op.compare_lower("vale1")) {
2695
      // SYS #0, C8, C7, #5
2696
0
      SYS_ALIAS(0, 8, 7, 5);
2697
0
    } else if (!Op.compare_lower("vale2")) {
2698
      // SYS #4, C8, C7, #5
2699
0
      SYS_ALIAS(4, 8, 7, 5);
2700
0
    } else if (!Op.compare_lower("vale3")) {
2701
      // SYS #6, C8, C7, #5
2702
0
      SYS_ALIAS(6, 8, 7, 5);
2703
0
    } else if (!Op.compare_lower("vaale1")) {
2704
      // SYS #0, C8, C7, #7
2705
0
      SYS_ALIAS(0, 8, 7, 7);
2706
0
    } else if (!Op.compare_lower("ipas2e1")) {
2707
      // SYS #4, C8, C4, #1
2708
0
      SYS_ALIAS(4, 8, 4, 1);
2709
0
    } else if (!Op.compare_lower("ipas2le1")) {
2710
      // SYS #4, C8, C4, #5
2711
0
      SYS_ALIAS(4, 8, 4, 5);
2712
0
    } else if (!Op.compare_lower("ipas2e1is")) {
2713
      // SYS #4, C8, C4, #1
2714
0
      SYS_ALIAS(4, 8, 0, 1);
2715
0
    } else if (!Op.compare_lower("ipas2le1is")) {
2716
      // SYS #4, C8, C4, #5
2717
0
      SYS_ALIAS(4, 8, 0, 5);
2718
0
    } else if (!Op.compare_lower("vmalls12e1")) {
2719
      // SYS #4, C8, C7, #6
2720
0
      SYS_ALIAS(4, 8, 7, 6);
2721
0
    } else if (!Op.compare_lower("vmalls12e1is")) {
2722
      // SYS #4, C8, C3, #6
2723
0
      SYS_ALIAS(4, 8, 3, 6);
2724
0
    } else {
2725
      //return TokError("invalid operand for TLBI instruction");
2726
0
      return true;
2727
0
    }
2728
0
  }
2729
2730
0
#undef SYS_ALIAS
2731
2732
0
  Parser.Lex(); // Eat operand.
2733
2734
0
  bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2735
0
  bool HasRegister = false;
2736
2737
  // Check for the optional register operand.
2738
0
  if (getLexer().is(AsmToken::Comma)) {
2739
0
    Parser.Lex(); // Eat comma.
2740
2741
0
    if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2742
      //return TokError("expected register operand");
2743
0
      return true;
2744
2745
0
    HasRegister = true;
2746
0
  }
2747
2748
0
  if (getLexer().isNot(AsmToken::EndOfStatement)) {
2749
0
    Parser.eatToEndOfStatement();
2750
    //return TokError("unexpected token in argument list");
2751
0
    return true;
2752
0
  }
2753
2754
0
  if (ExpectRegister && !HasRegister) {
2755
    //return TokError("specified " + Mnemonic + " op requires a register");
2756
0
    return true;
2757
0
  }
2758
0
  else if (!ExpectRegister && HasRegister) {
2759
    //return TokError("specified " + Mnemonic + " op does not use a register");
2760
0
    return true;
2761
0
  }
2762
2763
0
  Parser.Lex(); // Consume the EndOfStatement
2764
0
  return false;
2765
0
}
2766
2767
AArch64AsmParser::OperandMatchResultTy
2768
AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands)
2769
87
{
2770
87
  MCAsmParser &Parser = getParser();
2771
87
  const AsmToken &Tok = Parser.getTok();
2772
2773
  // Can be either a #imm style literal or an option name
2774
87
  bool Hash = Tok.is(AsmToken::Hash);
2775
87
  if (Hash || Tok.is(AsmToken::Integer)) {
2776
    // Immediate operand.
2777
65
    if (Hash)
2778
64
      Parser.Lex(); // Eat the '#'
2779
65
    const MCExpr *ImmVal;
2780
65
    SMLoc ExprLoc = getLoc();
2781
65
    if (getParser().parseExpression(ImmVal))
2782
33
      return MatchOperand_ParseFail;
2783
32
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2784
32
    if (!MCE) {
2785
      //Error(ExprLoc, "immediate value expected for barrier operand");
2786
0
      return MatchOperand_ParseFail;
2787
0
    }
2788
32
    if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2789
      //Error(ExprLoc, "barrier operand out of range");
2790
1
      return MatchOperand_ParseFail;
2791
1
    }
2792
31
    bool Valid;
2793
31
    auto Mapper = AArch64DB::DBarrierMapper();
2794
31
    StringRef Name = 
2795
31
        Mapper.toString(MCE->getValue(), getSTI().getFeatureBits(), Valid);
2796
31
    Operands.push_back( AArch64Operand::CreateBarrier(MCE->getValue(), Name,
2797
31
                                                      ExprLoc, getContext()));
2798
31
    return MatchOperand_Success;
2799
32
  }
2800
2801
22
  if (Tok.isNot(AsmToken::Identifier)) {
2802
    //TokError("invalid operand for instruction");
2803
1
    return MatchOperand_ParseFail;
2804
1
  }
2805
2806
21
  bool Valid;
2807
21
  auto Mapper = AArch64DB::DBarrierMapper();
2808
21
  unsigned Opt = 
2809
21
      Mapper.fromString(Tok.getString(), getSTI().getFeatureBits(), Valid);
2810
21
  if (!Valid) {
2811
    //TokError("invalid barrier option name");
2812
2
    return MatchOperand_ParseFail;
2813
2
  }
2814
2815
  // The only valid named option for ISB is 'sy'
2816
19
  if (Mnemonic == "isb" && Opt != AArch64DB::SY) {
2817
    //TokError("'sy' or #imm operand expected");
2818
0
    return MatchOperand_ParseFail;
2819
0
  }
2820
2821
19
  Operands.push_back( AArch64Operand::CreateBarrier(Opt, Tok.getString(),
2822
19
                                                    getLoc(), getContext()));
2823
19
  Parser.Lex(); // Consume the option
2824
2825
19
  return MatchOperand_Success;
2826
19
}
2827
2828
AArch64AsmParser::OperandMatchResultTy
2829
AArch64AsmParser::tryParseSysReg(OperandVector &Operands)
2830
621
{
2831
621
  MCAsmParser &Parser = getParser();
2832
621
  const AsmToken &Tok = Parser.getTok();
2833
2834
621
  if (Tok.isNot(AsmToken::Identifier))
2835
46
    return MatchOperand_NoMatch;
2836
2837
575
  bool IsKnown;
2838
575
  auto MRSMapper = AArch64SysReg::MRSMapper();
2839
575
  uint32_t MRSReg = MRSMapper.fromString(Tok.getString(),
2840
575
                                         getSTI().getFeatureBits(), IsKnown);
2841
575
  assert(IsKnown == (MRSReg != -1U) &&
2842
575
         "register should be -1 if and only if it's unknown");
2843
2844
575
  auto MSRMapper = AArch64SysReg::MSRMapper();
2845
575
  uint32_t MSRReg = MSRMapper.fromString(Tok.getString(),
2846
575
                                         getSTI().getFeatureBits(), IsKnown);
2847
575
  assert(IsKnown == (MSRReg != -1U) &&
2848
575
         "register should be -1 if and only if it's unknown");
2849
2850
575
  auto PStateMapper = AArch64PState::PStateMapper();
2851
575
  uint32_t PStateField = 
2852
575
      PStateMapper.fromString(Tok.getString(),
2853
575
                              getSTI().getFeatureBits(), IsKnown);
2854
575
  assert(IsKnown == (PStateField != -1U) &&
2855
575
         "register should be -1 if and only if it's unknown");
2856
2857
575
  Operands.push_back(AArch64Operand::CreateSysReg(
2858
575
      Tok.getString(), getLoc(), MRSReg, MSRReg, PStateField, getContext()));
2859
575
  Parser.Lex(); // Eat identifier
2860
2861
575
  return MatchOperand_Success;
2862
575
}
2863
2864
/// tryParseVectorRegister - Parse a vector register operand.
2865
// return true on error
2866
bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands)
2867
25.6k
{
2868
25.6k
  MCAsmParser &Parser = getParser();
2869
25.6k
  if (Parser.getTok().isNot(AsmToken::Identifier))
2870
0
    return true;
2871
2872
25.6k
  SMLoc S = getLoc();
2873
  // Check for a vector register specifier first.
2874
25.6k
  StringRef Kind;
2875
25.6k
  int64_t Reg = tryMatchVectorRegister(Kind, false);
2876
25.6k
  if (Reg == -1)
2877
23.7k
    return true;
2878
1.90k
  Operands.push_back(
2879
1.90k
      AArch64Operand::CreateReg(Reg, true, S, getLoc(), getContext()));
2880
  // If there was an explicit qualifier, that goes on as a literal text
2881
  // operand.
2882
1.90k
  if (!Kind.empty())
2883
1.26k
    Operands.push_back(
2884
1.26k
        AArch64Operand::CreateToken(Kind, false, S, getContext()));
2885
2886
  // If there is an index specifier following the register, parse that too.
2887
1.90k
  if (Parser.getTok().is(AsmToken::LBrac)) {
2888
0
    SMLoc SIdx = getLoc();
2889
0
    Parser.Lex(); // Eat left bracket token.
2890
2891
0
    const MCExpr *ImmVal;
2892
0
    if (getParser().parseExpression(ImmVal))
2893
0
      return false;
2894
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2895
0
    if (!MCE) {
2896
      //TokError("immediate value expected for vector index");
2897
0
      return true;
2898
0
    }
2899
2900
0
    SMLoc E = getLoc();
2901
0
    if (Parser.getTok().isNot(AsmToken::RBrac)) {
2902
      //Error(E, "']' expected");
2903
0
      return true;
2904
0
    }
2905
2906
0
    Parser.Lex(); // Eat right bracket token.
2907
2908
0
    Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2909
0
                                                         E, getContext()));
2910
0
  }
2911
2912
1.90k
  return false;
2913
1.90k
}
2914
2915
/// parseRegister - Parse a non-vector register operand.
2916
// return true on error
2917
bool AArch64AsmParser::parseRegister(OperandVector &Operands)
2918
25.6k
{
2919
25.6k
  MCAsmParser &Parser = getParser();
2920
25.6k
  SMLoc S = getLoc();
2921
  // Try for a vector register.
2922
25.6k
  if (!tryParseVectorRegister(Operands))
2923
1.90k
    return false;
2924
2925
  // Try for a scalar register.
2926
23.7k
  int64_t Reg = tryParseRegister();
2927
23.7k
  if (Reg == -1)
2928
20.0k
    return true;
2929
3.69k
  Operands.push_back(
2930
3.69k
      AArch64Operand::CreateReg(Reg, false, S, getLoc(), getContext()));
2931
2932
  // A small number of instructions (FMOVXDhighr, for example) have "[1]"
2933
  // as a string token in the instruction itself.
2934
3.69k
  if (getLexer().getKind() == AsmToken::LBrac) {
2935
38
    SMLoc LBracS = getLoc();
2936
38
    Parser.Lex();
2937
38
    const AsmToken &Tok = Parser.getTok();
2938
38
    if (Tok.is(AsmToken::Integer)) {
2939
1
      SMLoc IntS = getLoc();
2940
1
      bool valid;
2941
1
      int64_t Val = Tok.getIntVal(valid);
2942
1
      if (!valid)
2943
0
        return true;
2944
1
      if (Val == 1) {
2945
0
        Parser.Lex();
2946
0
        if (getLexer().getKind() == AsmToken::RBrac) {
2947
0
          SMLoc RBracS = getLoc();
2948
0
          Parser.Lex();
2949
0
          Operands.push_back(
2950
0
              AArch64Operand::CreateToken("[", false, LBracS, getContext()));
2951
0
          Operands.push_back(
2952
0
              AArch64Operand::CreateToken("1", false, IntS, getContext()));
2953
0
          Operands.push_back(
2954
0
              AArch64Operand::CreateToken("]", false, RBracS, getContext()));
2955
0
          return false;
2956
0
        }
2957
0
      }
2958
1
    }
2959
38
  }
2960
2961
3.69k
  return false;
2962
3.69k
}
2963
2964
bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal)
2965
13.5k
{
2966
13.5k
  MCAsmParser &Parser = getParser();
2967
13.5k
  bool HasELFModifier = false;
2968
13.5k
  AArch64MCExpr::VariantKind RefKind;
2969
2970
13.5k
  if (Parser.getTok().is(AsmToken::Colon)) {
2971
13
    Parser.Lex(); // Eat ':"
2972
13
    HasELFModifier = true;
2973
2974
13
    if (Parser.getTok().isNot(AsmToken::Identifier)) {
2975
      //Error(Parser.getTok().getLoc(),
2976
      //      "expect relocation specifier in operand after ':'");
2977
0
      return true;
2978
0
    }
2979
2980
13
    std::string LowerCase = Parser.getTok().getIdentifier().lower();
2981
13
    RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2982
13
                  .Case("lo12", AArch64MCExpr::VK_LO12)
2983
13
                  .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2984
13
                  .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2985
13
                  .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2986
13
                  .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2987
13
                  .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2988
13
                  .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2989
13
                  .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2990
13
                  .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2991
13
                  .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2992
13
                  .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2993
13
                  .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2994
13
                  .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2995
13
                  .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2996
13
                  .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2997
13
                  .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2998
13
                  .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2999
13
                  .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3000
13
                  .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3001
13
                  .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3002
13
                  .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3003
13
                  .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3004
13
                  .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3005
13
                  .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3006
13
                  .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3007
13
                  .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3008
13
                  .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3009
13
                  .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3010
13
                  .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3011
13
                  .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3012
13
                  .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3013
13
                  .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3014
13
                  .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3015
13
                  .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3016
13
                  .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
3017
13
                  .Default(AArch64MCExpr::VK_INVALID);
3018
3019
13
    if (RefKind == AArch64MCExpr::VK_INVALID) {
3020
      //Error(Parser.getTok().getLoc(),
3021
      //      "expect relocation specifier in operand after ':'");
3022
8
      return true;
3023
8
    }
3024
3025
5
    Parser.Lex(); // Eat identifier
3026
3027
5
    if (Parser.getTok().isNot(AsmToken::Colon)) {
3028
      //Error(Parser.getTok().getLoc(), "expect ':' after relocation specifier");
3029
0
      return true;
3030
0
    }
3031
5
    Parser.Lex(); // Eat ':'
3032
5
  }
3033
3034
13.5k
  if (getParser().parseExpression(ImmVal))
3035
9.68k
    return true;
3036
3037
3.85k
  if (HasELFModifier)
3038
5
    ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
3039
3040
3.85k
  return false;
3041
13.5k
}
3042
3043
/// parseVectorList - Parse a vector list operand for AdvSIMD instructions.
3044
// return true on error
3045
bool AArch64AsmParser::parseVectorList(OperandVector &Operands)
3046
82
{
3047
82
  MCAsmParser &Parser = getParser();
3048
82
  assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket");
3049
82
  SMLoc S = getLoc();
3050
82
  Parser.Lex(); // Eat left bracket token.
3051
82
  StringRef Kind;
3052
82
  int64_t FirstReg = tryMatchVectorRegister(Kind, true);
3053
82
  if (FirstReg == -1)
3054
6
    return true;
3055
76
  int64_t PrevReg = FirstReg;
3056
76
  unsigned Count = 1;
3057
3058
76
  if (Parser.getTok().is(AsmToken::Minus)) {
3059
0
    Parser.Lex(); // Eat the minus.
3060
3061
    //SMLoc Loc = getLoc();
3062
0
    StringRef NextKind;
3063
0
    int64_t Reg = tryMatchVectorRegister(NextKind, true);
3064
0
    if (Reg == -1)
3065
0
      return true;
3066
    // Any Kind suffices must match on all regs in the list.
3067
0
    if (Kind != NextKind)
3068
      //return Error(Loc, "mismatched register size suffix");
3069
0
      return true;
3070
3071
0
    unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3072
3073
0
    if (Space == 0 || Space > 3) {
3074
      //return Error(Loc, "invalid number of vectors");
3075
0
      return true;
3076
0
    }
3077
3078
0
    Count += Space;
3079
0
  }
3080
76
  else {
3081
76
    while (Parser.getTok().is(AsmToken::Comma)) {
3082
0
      Parser.Lex(); // Eat the comma token.
3083
3084
      //SMLoc Loc = getLoc();
3085
0
      StringRef NextKind;
3086
0
      int64_t Reg = tryMatchVectorRegister(NextKind, true);
3087
0
      if (Reg == -1)
3088
0
        return true;
3089
      // Any Kind suffices must match on all regs in the list.
3090
0
      if (Kind != NextKind)
3091
        //return Error(Loc, "mismatched register size suffix");
3092
0
        return true;
3093
3094
      // Registers must be incremental (with wraparound at 31)
3095
0
      if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
3096
0
          (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32)
3097
       //return Error(Loc, "registers must be sequential");
3098
0
       return true;
3099
3100
0
      PrevReg = Reg;
3101
0
      ++Count;
3102
0
    }
3103
76
  }
3104
3105
76
  if (Parser.getTok().isNot(AsmToken::RCurly))
3106
    //return Error(getLoc(), "'}' expected");
3107
0
    return true;
3108
76
  Parser.Lex(); // Eat the '}' token.
3109
3110
76
  if (Count > 4)
3111
    //return Error(S, "invalid number of vectors");
3112
0
    return true;
3113
3114
76
  unsigned NumElements = 0;
3115
76
  char ElementKind = 0;
3116
76
  if (!Kind.empty())
3117
0
    parseValidVectorKind(Kind, NumElements, ElementKind);
3118
3119
76
  Operands.push_back(AArch64Operand::CreateVectorList(
3120
76
      FirstReg, Count, NumElements, ElementKind, S, getLoc(), getContext()));
3121
3122
  // If there is an index specifier following the list, parse that too.
3123
76
  if (Parser.getTok().is(AsmToken::LBrac)) {
3124
35
    SMLoc SIdx = getLoc();
3125
35
    Parser.Lex(); // Eat left bracket token.
3126
3127
35
    const MCExpr *ImmVal;
3128
35
    if (getParser().parseExpression(ImmVal))
3129
35
      return false;
3130
0
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3131
0
    if (!MCE) {
3132
      //TokError("immediate value expected for vector index");
3133
0
      return false;
3134
0
    }
3135
3136
0
    SMLoc E = getLoc();
3137
0
    if (Parser.getTok().isNot(AsmToken::RBrac)) {
3138
      //Error(E, "']' expected");
3139
0
      return false;
3140
0
    }
3141
3142
0
    Parser.Lex(); // Eat right bracket token.
3143
3144
0
    Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3145
0
                                                         E, getContext()));
3146
0
  }
3147
41
  return false;
3148
76
}
3149
3150
AArch64AsmParser::OperandMatchResultTy
3151
AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands)
3152
440
{
3153
440
  MCAsmParser &Parser = getParser();
3154
440
  const AsmToken &Tok = Parser.getTok();
3155
440
  if (!Tok.is(AsmToken::Identifier))
3156
232
    return MatchOperand_NoMatch;
3157
3158
208
  unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), false);
3159
3160
208
  MCContext &Ctx = getContext();
3161
208
  const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3162
208
  if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3163
208
    return MatchOperand_NoMatch;
3164
3165
0
  SMLoc S = getLoc();
3166
0
  Parser.Lex(); // Eat register
3167
3168
0
  if (Parser.getTok().isNot(AsmToken::Comma)) {
3169
0
    Operands.push_back(
3170
0
        AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3171
0
    return MatchOperand_Success;
3172
0
  }
3173
0
  Parser.Lex(); // Eat comma.
3174
3175
0
  if (Parser.getTok().is(AsmToken::Hash))
3176
0
    Parser.Lex(); // Eat hash
3177
3178
0
  if (Parser.getTok().isNot(AsmToken::Integer)) {
3179
    //Error(getLoc(), "index must be absent or #0");
3180
0
    return MatchOperand_ParseFail;
3181
0
  }
3182
3183
0
  const MCExpr *ImmVal;
3184
0
  if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3185
0
      cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3186
    //Error(getLoc(), "index must be absent or #0");
3187
0
    return MatchOperand_ParseFail;
3188
0
  }
3189
3190
0
  Operands.push_back(
3191
0
      AArch64Operand::CreateReg(RegNum, false, S, getLoc(), Ctx));
3192
0
  return MatchOperand_Success;
3193
0
}
3194
3195
/// parseOperand - Parse a arm instruction operand.  For now this parses the
3196
/// operand regardless of the mnemonic.
3197
// return true on failure
3198
bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3199
                                  bool invertCondCode)
3200
100k
{
3201
100k
  MCAsmParser &Parser = getParser();
3202
  // Check if the current operand has a custom associated parser, if so, try to
3203
  // custom parse the operand, or fallback to the general approach.
3204
100k
  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3205
100k
  if (ResTy == MatchOperand_Success)
3206
641
    return false;
3207
  // If there wasn't a custom match, try the generic matcher below. Otherwise,
3208
  // there was a match, but an error occurred, in which case, just return that
3209
  // the operand parsing failed.
3210
99.6k
  if (ResTy == MatchOperand_ParseFail)
3211
397
    return true;
3212
3213
  // Nothing custom, so do general case parsing.
3214
99.2k
  SMLoc S, E;
3215
99.2k
  switch (getLexer().getKind()) {
3216
12.3k
  default: {
3217
12.3k
    SMLoc S = getLoc();
3218
12.3k
    const MCExpr *Expr;
3219
12.3k
    if (parseSymbolicImmVal(Expr))
3220
      //return Error(S, "invalid operand");
3221
9.59k
      return true;
3222
3223
2.77k
    SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3224
2.77k
    Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3225
2.77k
    return false;
3226
12.3k
  }
3227
58.6k
  case AsmToken::LBrac: {
3228
58.6k
    SMLoc Loc = Parser.getTok().getLoc();
3229
58.6k
    Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3230
58.6k
                                                   getContext()));
3231
58.6k
    Parser.Lex(); // Eat '['
3232
3233
    // There's no comma after a '[', so we can parse the next operand
3234
    // immediately.
3235
58.6k
    return parseOperand(Operands, false, false);
3236
12.3k
  }
3237
82
  case AsmToken::LCurly:
3238
82
    return parseVectorList(Operands);
3239
25.6k
  case AsmToken::Identifier: {
3240
    // If we're expecting a Condition Code operand, then just parse that.
3241
25.6k
    if (isCondCode)
3242
0
      return parseCondCode(Operands, invertCondCode);
3243
3244
    // If it's a register name, parse it.
3245
25.6k
    if (!parseRegister(Operands))
3246
5.59k
      return false;
3247
3248
    // This could be an optional "shift" or "extend" operand.
3249
20.0k
    OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3250
    // We can only continue if no tokens were eaten.
3251
20.0k
    if (GotShift != MatchOperand_NoMatch)
3252
78
      return GotShift;
3253
3254
    // This was not a register so parse other operands that start with an
3255
    // identifier (like labels) as expressions and create them as immediates.
3256
19.9k
    const MCExpr *IdVal;
3257
19.9k
    S = getLoc();
3258
19.9k
    if (getParser().parseExpression(IdVal))
3259
2.94k
      return true;
3260
3261
17.0k
    E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3262
17.0k
    Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3263
17.0k
    return false;
3264
19.9k
  }
3265
1.04k
  case AsmToken::Integer:
3266
1.05k
  case AsmToken::Real:
3267
1.16k
  case AsmToken::Hash: {
3268
    // #42 -> immediate.
3269
1.16k
    S = getLoc();
3270
1.16k
    if (getLexer().is(AsmToken::Hash))
3271
112
      Parser.Lex();
3272
3273
    // Parse a negative sign
3274
1.16k
    bool isNegative = false;
3275
1.16k
    if (Parser.getTok().is(AsmToken::Minus)) {
3276
6
      isNegative = true;
3277
      // We need to consume this token only when we have a Real, otherwise
3278
      // we let parseSymbolicImmVal take care of it
3279
6
      if (Parser.getLexer().peekTok().is(AsmToken::Real))
3280
0
        Parser.Lex();
3281
6
    }
3282
3283
    // The only Real that should come through here is a literal #0.0 for
3284
    // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3285
    // so convert the value.
3286
1.16k
    const AsmToken &Tok = Parser.getTok();
3287
1.16k
    if (Tok.is(AsmToken::Real)) {
3288
10
      APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3289
10
      if (RealVal.bitcastToAPInt().getActiveBits() > 64)
3290
0
          return true;
3291
10
      uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3292
10
      if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3293
10
          Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3294
10
          Mnemonic != "fcmlt")
3295
        //return TokError("unexpected floating point literal");
3296
10
        return true;
3297
0
      else if (IntVal != 0 || isNegative)
3298
        //return TokError("expected floating-point constant #0.0");
3299
0
        return true;
3300
0
      Parser.Lex(); // Eat the token.
3301
3302
0
      Operands.push_back(
3303
0
          AArch64Operand::CreateToken("#0", false, S, getContext()));
3304
0
      Operands.push_back(
3305
0
          AArch64Operand::CreateToken(".0", false, S, getContext()));
3306
0
      return false;
3307
10
    }
3308
3309
1.15k
    const MCExpr *ImmVal;
3310
1.15k
    if (parseSymbolicImmVal(ImmVal))
3311
97
      return true;
3312
3313
1.06k
    E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3314
1.06k
    Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3315
1.06k
    return false;
3316
1.15k
  }
3317
1.32k
  case AsmToken::Equal: {
3318
1.32k
    SMLoc Loc = Parser.getTok().getLoc();
3319
1.32k
    if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
3320
      //return Error(Loc, "unexpected token in operand");
3321
0
      return true;
3322
1.32k
    Parser.Lex(); // Eat '='
3323
1.32k
    const MCExpr *SubExprVal;
3324
1.32k
    if (getParser().parseExpression(SubExprVal))
3325
135
      return true;
3326
3327
1.19k
    if (Operands.size() < 2 ||
3328
1.19k
        !static_cast<AArch64Operand &>(*Operands[1]).isReg())
3329
      //return Error(Loc, "Only valid when first operand is register");
3330
0
      return true;
3331
3332
1.19k
    bool IsXReg =
3333
1.19k
        AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3334
1.19k
            Operands[1]->getReg());
3335
3336
1.19k
    MCContext& Ctx = getContext();
3337
1.19k
    E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3338
    // If the op is an imm and can be fit into a mov, then replace ldr with mov.
3339
1.19k
    if (isa<MCConstantExpr>(SubExprVal)) {
3340
968
      uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3341
968
      uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3342
1.55k
      while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3343
591
        ShiftAmt += 16;
3344
591
        Imm >>= 16;
3345
591
      }
3346
968
      if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3347
733
          Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3348
733
          Operands.push_back(AArch64Operand::CreateImm(
3349
733
                     MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
3350
733
        if (ShiftAmt)
3351
197
          Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3352
197
                     ShiftAmt, true, S, E, Ctx));
3353
733
        return false;
3354
733
      }
3355
235
      APInt Simm = APInt(64, Imm << ShiftAmt);
3356
      // check if the immediate is an unsigned or signed 32-bit int for W regs
3357
235
      if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3358
        //return Error(Loc, "Immediate too large for register");
3359
0
        return true;
3360
235
    }
3361
    // If it is a label or an imm that cannot fit in a movz, put it into CP.
3362
459
    const MCExpr *CPLoc =
3363
459
        getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
3364
459
    Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3365
459
    return false;
3366
1.19k
  }
3367
99.2k
  }
3368
99.2k
}
3369
3370
/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3371
/// operands.
3372
// return true on error
3373
bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3374
                                        StringRef Name, SMLoc NameLoc,
3375
                                        OperandVector &Operands, unsigned int &ErrorCode)
3376
15.9k
{
3377
15.9k
  MCAsmParser &Parser = getParser();
3378
15.9k
  Name = StringSwitch<StringRef>(Name.lower())
3379
15.9k
             .Case("beq", "b.eq")
3380
15.9k
             .Case("bne", "b.ne")
3381
15.9k
             .Case("bhs", "b.hs")
3382
15.9k
             .Case("bcs", "b.cs")
3383
15.9k
             .Case("blo", "b.lo")
3384
15.9k
             .Case("bcc", "b.cc")
3385
15.9k
             .Case("bmi", "b.mi")
3386
15.9k
             .Case("bpl", "b.pl")
3387
15.9k
             .Case("bvs", "b.vs")
3388
15.9k
             .Case("bvc", "b.vc")
3389
15.9k
             .Case("bhi", "b.hi")
3390
15.9k
             .Case("bls", "b.ls")
3391
15.9k
             .Case("bge", "b.ge")
3392
15.9k
             .Case("blt", "b.lt")
3393
15.9k
             .Case("bgt", "b.gt")
3394
15.9k
             .Case("ble", "b.le")
3395
15.9k
             .Case("bal", "b.al")
3396
15.9k
             .Case("bnv", "b.nv")
3397
15.9k
             .Default(Name);
3398
3399
  // First check for the AArch64-specific .req directive.
3400
15.9k
  if (Parser.getTok().is(AsmToken::Identifier) &&
3401
4.90k
      Parser.getTok().getIdentifier() == ".req") {
3402
0
    parseDirectiveReq(Name, NameLoc);
3403
    // We always return 'error' for this, as we're done with this
3404
    // statement and don't need to match the 'instruction."
3405
0
    return true;
3406
0
  }
3407
3408
  // Create the leading tokens for the mnemonic, split by '.' characters.
3409
15.9k
  size_t Start = 0, Next = Name.find('.');
3410
15.9k
  StringRef Head = Name.slice(Start, Next);
3411
3412
  // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
3413
15.9k
  if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi") {
3414
1
    bool IsError = parseSysAlias(Head, NameLoc, Operands);
3415
1
    if (IsError && getLexer().isNot(AsmToken::EndOfStatement))
3416
0
      Parser.eatToEndOfStatement();
3417
1
    return IsError;
3418
1
  }
3419
3420
15.9k
  Operands.push_back(
3421
15.9k
      AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3422
15.9k
  Mnemonic = Head;
3423
3424
  // Handle condition codes for a branch mnemonic
3425
15.9k
  if (Head == "b" && Next != StringRef::npos) {
3426
490
    Start = Next;
3427
490
    Next = Name.find('.', Start + 1);
3428
490
    Head = Name.slice(Start + 1, Next);
3429
3430
490
    SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3431
490
                                            (Head.data() - Name.data()));
3432
490
    AArch64CC::CondCode CC = parseCondCodeString(Head);
3433
490
    if (CC == AArch64CC::Invalid)
3434
      //return Error(SuffixLoc, "invalid condition code");
3435
7
      return true;
3436
483
    Operands.push_back(
3437
483
        AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3438
483
    Operands.push_back(
3439
483
        AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3440
483
  }
3441
3442
  // Add the remaining tokens in the mnemonic.
3443
34.9k
  while (Next != StringRef::npos) {
3444
18.9k
    Start = Next;
3445
18.9k
    Next = Name.find('.', Start + 1);
3446
18.9k
    Head = Name.slice(Start, Next);
3447
18.9k
    SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3448
18.9k
                                            (Head.data() - Name.data()) + 1);
3449
18.9k
    Operands.push_back(
3450
18.9k
        AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3451
18.9k
  }
3452
3453
  // Conditional compare instructions have a Condition Code operand, which needs
3454
  // to be parsed and an immediate operand created.
3455
15.9k
  bool condCodeFourthOperand =
3456
15.9k
      (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3457
13.9k
       Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3458
13.9k
       Head == "csinc" || Head == "csinv" || Head == "csneg");
3459
3460
  // These instructions are aliases to some of the conditional select
3461
  // instructions. However, the condition code is inverted in the aliased
3462
  // instruction.
3463
  //
3464
  // FIXME: Is this the correct way to handle these? Or should the parser
3465
  //        generate the aliased instructions directly?
3466
15.9k
  bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3467
15.9k
  bool condCodeThirdOperand =
3468
15.9k
      (Head == "cinc" || Head == "cinv" || Head == "cneg");
3469
3470
  // Read the remaining operands.
3471
15.9k
  if (getLexer().isNot(AsmToken::EndOfStatement)) {
3472
    // Read the first operand.
3473
15.3k
    if (parseOperand(Operands, false, false)) {
3474
11.7k
      Parser.eatToEndOfStatement();
3475
11.7k
      ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
3476
11.7k
      return true;
3477
11.7k
    }
3478
3479
3.61k
    unsigned N = 2;
3480
28.4k
    while (getLexer().is(AsmToken::Comma)) {
3481
26.2k
      Parser.Lex(); // Eat the comma.
3482
3483
      // Parse and remember the operand.
3484
26.2k
      if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3485
26.2k
                                     (N == 3 && condCodeThirdOperand) ||
3486
26.2k
                                     (N == 2 && condCodeSecondOperand),
3487
26.2k
                       condCodeSecondOperand || condCodeThirdOperand)) {
3488
1.43k
        Parser.eatToEndOfStatement();
3489
1.43k
        ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
3490
1.43k
        return true;
3491
1.43k
      }
3492
3493
      // After successfully parsing some operands there are two special cases to
3494
      // consider (i.e. notional operands not separated by commas). Both are due
3495
      // to memory specifiers:
3496
      //  + An RBrac will end an address for load/store/prefetch
3497
      //  + An '!' will indicate a pre-indexed operation.
3498
      //
3499
      // It's someone else's responsibility to make sure these tokens are sane
3500
      // in the given context!
3501
24.8k
      if (Parser.getTok().is(AsmToken::RBrac)) {
3502
301
        SMLoc Loc = Parser.getTok().getLoc();
3503
301
        Operands.push_back(AArch64Operand::CreateToken("]", false, Loc,
3504
301
                                                       getContext()));
3505
301
        Parser.Lex();
3506
301
      }
3507
3508
24.8k
      if (Parser.getTok().is(AsmToken::Exclaim)) {
3509
207
        SMLoc Loc = Parser.getTok().getLoc();
3510
207
        Operands.push_back(AArch64Operand::CreateToken("!", false, Loc,
3511
207
                                                       getContext()));
3512
207
        Parser.Lex();
3513
207
      }
3514
3515
24.8k
      ++N;
3516
24.8k
    }
3517
3.61k
  }
3518
3519
2.74k
  if (getLexer().isNot(AsmToken::EndOfStatement)) {
3520
    //SMLoc Loc = Parser.getTok().getLoc();
3521
245
    Parser.eatToEndOfStatement();
3522
    //return Error(Loc, "unexpected token in argument list");
3523
245
    return true;
3524
245
  }
3525
3526
2.50k
  Parser.Lex(); // Consume the EndOfStatement
3527
2.50k
  return false;
3528
2.74k
}
3529
3530
// FIXME: This entire function is a giant hack to provide us with decent
3531
// operand range validation/diagnostics until TableGen/MC can be extended
3532
// to support autogeneration of this kind of validation.
3533
bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3534
                                         SmallVectorImpl<SMLoc> &Loc)
3535
2.16k
{
3536
2.16k
  const MCRegisterInfo *RI = getContext().getRegisterInfo();
3537
  // Check for indexed addressing modes w/ the base register being the
3538
  // same as a destination/source register or pair load where
3539
  // the Rt == Rt2. All of those are undefined behaviour.
3540
2.16k
  switch (Inst.getOpcode()) {
3541
0
  case AArch64::LDPSWpre:
3542
0
  case AArch64::LDPWpost:
3543
0
  case AArch64::LDPWpre:
3544
0
  case AArch64::LDPXpost:
3545
0
  case AArch64::LDPXpre: {
3546
0
    unsigned Rt = Inst.getOperand(1).getReg();
3547
0
    unsigned Rt2 = Inst.getOperand(2).getReg();
3548
0
    unsigned Rn = Inst.getOperand(3).getReg();
3549
0
    if (RI->isSubRegisterEq(Rn, Rt))
3550
      //return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3551
      //                     "is also a destination");
3552
0
      return true;
3553
0
    if (RI->isSubRegisterEq(Rn, Rt2))
3554
      //return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3555
      //                     "is also a destination");
3556
0
      return true;
3557
    // FALLTHROUGH
3558
0
  }
3559
0
  case AArch64::LDPDi:
3560
0
  case AArch64::LDPQi:
3561
0
  case AArch64::LDPSi:
3562
0
  case AArch64::LDPSWi:
3563
0
  case AArch64::LDPWi:
3564
0
  case AArch64::LDPXi: {
3565
0
    unsigned Rt = Inst.getOperand(0).getReg();
3566
0
    unsigned Rt2 = Inst.getOperand(1).getReg();
3567
0
    if (Rt == Rt2)
3568
      //return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3569
0
      return true;
3570
0
    break;
3571
0
  }
3572
0
  case AArch64::LDPDpost:
3573
0
  case AArch64::LDPDpre:
3574
0
  case AArch64::LDPQpost:
3575
0
  case AArch64::LDPQpre:
3576
0
  case AArch64::LDPSpost:
3577
0
  case AArch64::LDPSpre:
3578
0
  case AArch64::LDPSWpost: {
3579
0
    unsigned Rt = Inst.getOperand(1).getReg();
3580
0
    unsigned Rt2 = Inst.getOperand(2).getReg();
3581
0
    if (Rt == Rt2)
3582
      //return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3583
0
      return true;
3584
0
    break;
3585
0
  }
3586
0
  case AArch64::STPDpost:
3587
0
  case AArch64::STPDpre:
3588
0
  case AArch64::STPQpost:
3589
0
  case AArch64::STPQpre:
3590
0
  case AArch64::STPSpost:
3591
0
  case AArch64::STPSpre:
3592
0
  case AArch64::STPWpost:
3593
0
  case AArch64::STPWpre:
3594
0
  case AArch64::STPXpost:
3595
0
  case AArch64::STPXpre: {
3596
0
    unsigned Rt = Inst.getOperand(1).getReg();
3597
0
    unsigned Rt2 = Inst.getOperand(2).getReg();
3598
0
    unsigned Rn = Inst.getOperand(3).getReg();
3599
0
    if (RI->isSubRegisterEq(Rn, Rt))
3600
      //return Error(Loc[0], "unpredictable STP instruction, writeback base "
3601
      //                     "is also a source");
3602
0
      return true;
3603
0
    if (RI->isSubRegisterEq(Rn, Rt2))
3604
      //return Error(Loc[1], "unpredictable STP instruction, writeback base "
3605
      //                     "is also a source");
3606
0
      return true;
3607
0
    break;
3608
0
  }
3609
0
  case AArch64::LDRBBpre:
3610
0
  case AArch64::LDRBpre:
3611
0
  case AArch64::LDRHHpre:
3612
0
  case AArch64::LDRHpre:
3613
0
  case AArch64::LDRSBWpre:
3614
0
  case AArch64::LDRSBXpre:
3615
0
  case AArch64::LDRSHWpre:
3616
0
  case AArch64::LDRSHXpre:
3617
0
  case AArch64::LDRSWpre:
3618
0
  case AArch64::LDRWpre:
3619
0
  case AArch64::LDRXpre:
3620
0
  case AArch64::LDRBBpost:
3621
0
  case AArch64::LDRBpost:
3622
0
  case AArch64::LDRHHpost:
3623
0
  case AArch64::LDRHpost:
3624
0
  case AArch64::LDRSBWpost:
3625
0
  case AArch64::LDRSBXpost:
3626
0
  case AArch64::LDRSHWpost:
3627
0
  case AArch64::LDRSHXpost:
3628
0
  case AArch64::LDRSWpost:
3629
0
  case AArch64::LDRWpost:
3630
0
  case AArch64::LDRXpost: {
3631
0
    unsigned Rt = Inst.getOperand(1).getReg();
3632
0
    unsigned Rn = Inst.getOperand(2).getReg();
3633
0
    if (RI->isSubRegisterEq(Rn, Rt))
3634
      //return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3635
      //                     "is also a source");
3636
0
      return true;
3637
0
    break;
3638
0
  }
3639
0
  case AArch64::STRBBpost:
3640
0
  case AArch64::STRBpost:
3641
0
  case AArch64::STRHHpost:
3642
0
  case AArch64::STRHpost:
3643
0
  case AArch64::STRWpost:
3644
0
  case AArch64::STRXpost:
3645
0
  case AArch64::STRBBpre:
3646
0
  case AArch64::STRBpre:
3647
0
  case AArch64::STRHHpre:
3648
0
  case AArch64::STRHpre:
3649
0
  case AArch64::STRWpre:
3650
0
  case AArch64::STRXpre: {
3651
0
    unsigned Rt = Inst.getOperand(1).getReg();
3652
0
    unsigned Rn = Inst.getOperand(2).getReg();
3653
0
    if (RI->isSubRegisterEq(Rn, Rt))
3654
      //return Error(Loc[0], "unpredictable STR instruction, writeback base "
3655
      //                     "is also a source");
3656
0
      return true;
3657
0
    break;
3658
0
  }
3659
2.16k
  }
3660
3661
  // Now check immediate ranges. Separate from the above as there is overlap
3662
  // in the instructions being checked and this keeps the nested conditionals
3663
  // to a minimum.
3664
2.16k
  switch (Inst.getOpcode()) {
3665
0
  case AArch64::ADDSWri:
3666
0
  case AArch64::ADDSXri:
3667
0
  case AArch64::ADDWri:
3668
7
  case AArch64::ADDXri:
3669
7
  case AArch64::SUBSWri:
3670
7
  case AArch64::SUBSXri:
3671
7
  case AArch64::SUBWri:
3672
11
  case AArch64::SUBXri: {
3673
    // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3674
    // some slight duplication here.
3675
11
    if (Inst.getOperand(2).isExpr()) {
3676
0
      const MCExpr *Expr = Inst.getOperand(2).getExpr();
3677
0
      AArch64MCExpr::VariantKind ELFRefKind;
3678
0
      MCSymbolRefExpr::VariantKind DarwinRefKind;
3679
0
      int64_t Addend;
3680
0
      if (!classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3681
        //return Error(Loc[2], "invalid immediate expression");
3682
0
        return true;
3683
0
      }
3684
3685
      // Only allow these with ADDXri.
3686
0
      if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3687
0
          DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3688
0
          Inst.getOpcode() == AArch64::ADDXri)
3689
0
        return false;
3690
3691
      // Only allow these with ADDXri/ADDWri
3692
0
      if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3693
0
          ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3694
0
          ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3695
0
          ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3696
0
          ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3697
0
          ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3698
0
          ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
3699
0
          ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) &&
3700
0
          (Inst.getOpcode() == AArch64::ADDXri ||
3701
0
          Inst.getOpcode() == AArch64::ADDWri))
3702
0
        return false;
3703
3704
      // Don't allow expressions in the immediate field otherwise
3705
      //return Error(Loc[2], "invalid immediate expression");
3706
0
      return true;
3707
0
    }
3708
11
    return false;
3709
11
  }
3710
2.15k
  default:
3711
2.15k
    return false;
3712
2.16k
  }
3713
2.16k
}
3714
3715
bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode)
3716
329
{
3717
329
  switch (ErrCode) {
3718
0
  case Match_MissingFeature:
3719
    //return Error(Loc,
3720
    //             "instruction requires a CPU feature not currently enabled");
3721
0
    return true;
3722
105
  case Match_InvalidOperand:
3723
    //return Error(Loc, "invalid operand for instruction");
3724
105
    return true;
3725
14
  case Match_InvalidSuffix:
3726
    //return Error(Loc, "invalid type suffix for instruction");
3727
14
    return true;
3728
0
  case Match_InvalidCondCode:
3729
    //return Error(Loc, "expected AArch64 condition code");
3730
0
    return true;
3731
0
  case Match_AddSubRegExtendSmall:
3732
    //return Error(Loc,
3733
    //  "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3734
0
    return true;
3735
0
  case Match_AddSubRegExtendLarge:
3736
    //return Error(Loc,
3737
    //  "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3738
0
    return true;
3739
0
  case Match_AddSubSecondSource:
3740
    //return Error(Loc,
3741
    //  "expected compatible register, symbol or integer in range [0, 4095]");
3742
0
    return true;
3743
1
  case Match_LogicalSecondSource:
3744
    //return Error(Loc, "expected compatible register or logical immediate");
3745
1
    return true;
3746
0
  case Match_InvalidMovImm32Shift:
3747
    //return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3748
0
    return true;
3749
0
  case Match_InvalidMovImm64Shift:
3750
    //return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3751
0
    return true;
3752
0
  case Match_AddSubRegShift32:
3753
    //return Error(Loc,
3754
    //   "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3755
0
    return true;
3756
0
  case Match_AddSubRegShift64:
3757
    //return Error(Loc,
3758
    //   "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3759
0
    return true;
3760
0
  case Match_InvalidFPImm:
3761
    //return Error(Loc,
3762
    //             "expected compatible register or floating-point constant");
3763
0
    return true;
3764
0
  case Match_InvalidMemoryIndexedSImm9:
3765
    //return Error(Loc, "index must be an integer in range [-256, 255].");
3766
0
    return true;
3767
0
  case Match_InvalidMemoryIndexed4SImm7:
3768
    //return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3769
0
    return true;
3770
0
  case Match_InvalidMemoryIndexed8SImm7:
3771
    //return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3772
0
    return true;
3773
0
  case Match_InvalidMemoryIndexed16SImm7:
3774
    //return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3775
0
    return true;
3776
0
  case Match_InvalidMemoryWExtend8:
3777
    //return Error(Loc,
3778
    //             "expected 'uxtw' or 'sxtw' with optional shift of #0");
3779
0
    return true;
3780
0
  case Match_InvalidMemoryWExtend16:
3781
    //return Error(Loc,
3782
    //             "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3783
0
    return true;
3784
0
  case Match_InvalidMemoryWExtend32:
3785
    //return Error(Loc,
3786
    //             "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3787
0
    return true;
3788
0
  case Match_InvalidMemoryWExtend64:
3789
    //return Error(Loc,
3790
    //             "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3791
0
    return true;
3792
0
  case Match_InvalidMemoryWExtend128:
3793
    //return Error(Loc,
3794
    //             "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3795
0
    return true;
3796
0
  case Match_InvalidMemoryXExtend8:
3797
    //return Error(Loc,
3798
    //             "expected 'lsl' or 'sxtx' with optional shift of #0");
3799
0
    return true;
3800
0
  case Match_InvalidMemoryXExtend16:
3801
    //return Error(Loc,
3802
    //             "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3803
0
    return true;
3804
0
  case Match_InvalidMemoryXExtend32:
3805
    //return Error(Loc,
3806
    //             "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3807
0
    return true;
3808
0
  case Match_InvalidMemoryXExtend64:
3809
    //return Error(Loc,
3810
    //             "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3811
0
    return true;
3812
0
  case Match_InvalidMemoryXExtend128:
3813
    //return Error(Loc,
3814
    //             "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3815
0
    return true;
3816
0
  case Match_InvalidMemoryIndexed1:
3817
    //return Error(Loc, "index must be an integer in range [0, 4095].");
3818
0
    return true;
3819
0
  case Match_InvalidMemoryIndexed2:
3820
    //return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3821
0
    return true;
3822
0
  case Match_InvalidMemoryIndexed4:
3823
    //return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3824
0
    return true;
3825
0
  case Match_InvalidMemoryIndexed8:
3826
    //return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3827
0
    return true;
3828
0
  case Match_InvalidMemoryIndexed16:
3829
    //return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
3830
0
    return true;
3831
0
  case Match_InvalidImm0_1:
3832
    //return Error(Loc, "immediate must be an integer in range [0, 1].");
3833
0
    return true;
3834
0
  case Match_InvalidImm0_7:
3835
    //return Error(Loc, "immediate must be an integer in range [0, 7].");
3836
0
    return true;
3837
0
  case Match_InvalidImm0_15:
3838
    //return Error(Loc, "immediate must be an integer in range [0, 15].");
3839
0
    return true;
3840
0
  case Match_InvalidImm0_31:
3841
    //return Error(Loc, "immediate must be an integer in range [0, 31].");
3842
0
    return true;
3843
0
  case Match_InvalidImm0_63:
3844
    //return Error(Loc, "immediate must be an integer in range [0, 63].");
3845
0
    return true;
3846
1
  case Match_InvalidImm0_127:
3847
    //return Error(Loc, "immediate must be an integer in range [0, 127].");
3848
1
    return true;
3849
0
  case Match_InvalidImm0_65535:
3850
    //return Error(Loc, "immediate must be an integer in range [0, 65535].");
3851
0
    return true;
3852
0
  case Match_InvalidImm1_8:
3853
    //return Error(Loc, "immediate must be an integer in range [1, 8].");
3854
0
    return true;
3855
0
  case Match_InvalidImm1_16:
3856
    //return Error(Loc, "immediate must be an integer in range [1, 16].");
3857
0
    return true;
3858
0
  case Match_InvalidImm1_32:
3859
    //return Error(Loc, "immediate must be an integer in range [1, 32].");
3860
0
    return true;
3861
0
  case Match_InvalidImm1_64:
3862
    //return Error(Loc, "immediate must be an integer in range [1, 64].");
3863
0
    return true;
3864
0
  case Match_InvalidIndex1:
3865
    //return Error(Loc, "expected lane specifier '[1]'");
3866
0
    return true;
3867
0
  case Match_InvalidIndexB:
3868
    //return Error(Loc, "vector lane must be an integer in range [0, 15].");
3869
0
    return true;
3870
0
  case Match_InvalidIndexH:
3871
    //return Error(Loc, "vector lane must be an integer in range [0, 7].");
3872
0
    return true;
3873
0
  case Match_InvalidIndexS:
3874
    //return Error(Loc, "vector lane must be an integer in range [0, 3].");
3875
0
    return true;
3876
0
  case Match_InvalidIndexD:
3877
    //return Error(Loc, "vector lane must be an integer in range [0, 1].");
3878
0
    return true;
3879
0
  case Match_InvalidLabel:
3880
    //return Error(Loc, "expected label or encodable integer pc offset");
3881
0
    return true;
3882
0
  case Match_MRS:
3883
    //return Error(Loc, "expected readable system register");
3884
0
    return true;
3885
2
  case Match_MSR:
3886
    //return Error(Loc, "expected writable system register or pstate");
3887
2
    return true;
3888
206
  case Match_MnemonicFail:
3889
    //return Error(Loc, "unrecognized instruction mnemonic");
3890
206
    return true;
3891
0
  default:
3892
0
    llvm_unreachable("unexpected error code!");
3893
329
  }
3894
329
}
3895
3896
static const char *getSubtargetFeatureName(uint64_t Val);
3897
3898
// return True on error
3899
bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3900
                                               OperandVector &Operands,
3901
                                               MCStreamer &Out,
3902
                                               uint64_t &ErrorInfo,
3903
                                               bool MatchingInlineAsm, unsigned int &ErrorCode, uint64_t &Address)
3904
2.50k
{
3905
2.50k
  assert(!Operands.empty() && "Unexpect empty operand list!");
3906
2.50k
  AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3907
2.50k
  assert(Op.isToken() && "Leading operand should always be a mnemonic!");
3908
3909
2.50k
  StringRef Tok = Op.getToken();
3910
2.50k
  unsigned NumOperands = Operands.size();
3911
3912
2.50k
  if (NumOperands == 4 && Tok == "lsl") {
3913
0
    AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3914
0
    AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3915
0
    if (Op2.isReg() && Op3.isImm()) {
3916
0
      const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3917
0
      if (Op3CE) {
3918
0
        uint64_t Op3Val = Op3CE->getValue();
3919
0
        uint64_t NewOp3Val = 0;
3920
0
        uint64_t NewOp4Val = 0;
3921
0
        if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
3922
0
                Op2.getReg())) {
3923
0
          NewOp3Val = (32 - Op3Val) & 0x1f;
3924
0
          NewOp4Val = 31 - Op3Val;
3925
0
        } else {
3926
0
          NewOp3Val = (64 - Op3Val) & 0x3f;
3927
0
          NewOp4Val = 63 - Op3Val;
3928
0
        }
3929
3930
0
        const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3931
0
        const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
3932
3933
0
        Operands[0] = AArch64Operand::CreateToken(
3934
0
            "ubfm", false, Op.getStartLoc(), getContext());
3935
0
        Operands.push_back(AArch64Operand::CreateImm(
3936
0
            NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3937
0
        Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3938
0
                                                Op3.getEndLoc(), getContext());
3939
0
      }
3940
0
    }
3941
2.50k
  } else if (NumOperands == 4 && Tok == "bfc") {
3942
    // FIXME: Horrible hack to handle BFC->BFM alias.
3943
0
    AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3944
0
    AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3945
0
    AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3946
3947
0
    if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) {
3948
0
      const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3949
0
      const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3950
3951
0
      if (LSBCE && WidthCE) {
3952
0
        uint64_t LSB = LSBCE->getValue();
3953
0
        uint64_t Width = WidthCE->getValue();
3954
3955
0
        uint64_t RegWidth = 0;
3956
0
        if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3957
0
                Op1.getReg()))
3958
0
          RegWidth = 64;
3959
0
        else
3960
0
          RegWidth = 32;
3961
3962
0
        if (LSB >= RegWidth) {
3963
          //return Error(LSBOp.getStartLoc(),
3964
          //             "expected integer in range [0, 31]");
3965
0
          ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
3966
0
          return true;
3967
0
        }
3968
0
        if (Width < 1 || Width > RegWidth) {
3969
          //return Error(WidthOp.getStartLoc(),
3970
          //             "expected integer in range [1, 32]");
3971
0
          ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
3972
0
          return true;
3973
0
        }
3974
3975
0
        uint64_t ImmR = 0;
3976
0
        if (RegWidth == 32)
3977
0
          ImmR = (32 - LSB) & 0x1f;
3978
0
        else
3979
0
          ImmR = (64 - LSB) & 0x3f;
3980
3981
0
        uint64_t ImmS = Width - 1;
3982
3983
0
        if (ImmR != 0 && ImmS >= ImmR) {
3984
          //return Error(WidthOp.getStartLoc(),
3985
          //             "requested insert overflows register");
3986
0
          ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
3987
0
          return true;
3988
0
        }
3989
3990
0
        const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3991
0
        const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
3992
0
        Operands[0] = AArch64Operand::CreateToken(
3993
0
              "bfm", false, Op.getStartLoc(), getContext());
3994
0
        Operands[2] = AArch64Operand::CreateReg(
3995
0
            RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(),
3996
0
            SMLoc(), getContext());
3997
0
        Operands[3] = AArch64Operand::CreateImm(
3998
0
            ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3999
0
        Operands.emplace_back(
4000
0
            AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4001
0
                                      WidthOp.getEndLoc(), getContext()));
4002
0
      }
4003
0
    }
4004
2.50k
  } else if (NumOperands == 5) {
4005
    // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4006
    // UBFIZ -> UBFM aliases.
4007
150
    if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
4008
0
      AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4009
0
      AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4010
0
      AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
4011
4012
0
      if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
4013
0
        const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4014
0
        const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
4015
4016
0
        if (Op3CE && Op4CE) {
4017
0
          uint64_t Op3Val = Op3CE->getValue();
4018
0
          uint64_t Op4Val = Op4CE->getValue();
4019
4020
0
          uint64_t RegWidth = 0;
4021
0
          if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4022
0
                  Op1.getReg()))
4023
0
            RegWidth = 64;
4024
0
          else
4025
0
            RegWidth = 32;
4026
4027
0
          if (Op3Val >= RegWidth) {
4028
            //return Error(Op3.getStartLoc(),
4029
            //             "expected integer in range [0, 31]");
4030
0
            ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
4031
0
            return true;
4032
0
          }
4033
0
          if (Op4Val < 1 || Op4Val > RegWidth) {
4034
            //return Error(Op4.getStartLoc(),
4035
            //             "expected integer in range [1, 32]");
4036
0
            ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
4037
0
            return true;
4038
0
          }
4039
4040
0
          uint64_t NewOp3Val = 0;
4041
0
          if (RegWidth == 32)
4042
0
            NewOp3Val = (32 - Op3Val) & 0x1f;
4043
0
          else
4044
0
            NewOp3Val = (64 - Op3Val) & 0x3f;
4045
4046
0
          uint64_t NewOp4Val = Op4Val - 1;
4047
4048
0
          if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val) {
4049
            //return Error(Op4.getStartLoc(),
4050
            //             "requested insert overflows register");
4051
0
            ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
4052
0
            return true;
4053
0
          }
4054
4055
0
          const MCExpr *NewOp3 =
4056
0
              MCConstantExpr::create(NewOp3Val, getContext());
4057
0
          const MCExpr *NewOp4 =
4058
0
              MCConstantExpr::create(NewOp4Val, getContext());
4059
0
          Operands[3] = AArch64Operand::CreateImm(
4060
0
              NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
4061
0
          Operands[4] = AArch64Operand::CreateImm(
4062
0
              NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
4063
0
          if (Tok == "bfi")
4064
0
            Operands[0] = AArch64Operand::CreateToken(
4065
0
                "bfm", false, Op.getStartLoc(), getContext());
4066
0
          else if (Tok == "sbfiz")
4067
0
            Operands[0] = AArch64Operand::CreateToken(
4068
0
                "sbfm", false, Op.getStartLoc(), getContext());
4069
0
          else if (Tok == "ubfiz")
4070
0
            Operands[0] = AArch64Operand::CreateToken(
4071
0
                "ubfm", false, Op.getStartLoc(), getContext());
4072
0
          else
4073
0
            llvm_unreachable("No valid mnemonic for alias?");
4074
0
        }
4075
0
      }
4076
4077
      // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4078
      // UBFX -> UBFM aliases.
4079
150
    } else if (NumOperands == 5 &&
4080
150
               (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
4081
0
      AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4082
0
      AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4083
0
      AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
4084
4085
0
      if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
4086
0
        const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4087
0
        const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
4088
4089
0
        if (Op3CE && Op4CE) {
4090
0
          uint64_t Op3Val = Op3CE->getValue();
4091
0
          uint64_t Op4Val = Op4CE->getValue();
4092
4093
0
          uint64_t RegWidth = 0;
4094
0
          if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4095
0
                  Op1.getReg()))
4096
0
            RegWidth = 64;
4097
0
          else
4098
0
            RegWidth = 32;
4099
4100
0
          if (Op3Val >= RegWidth) {
4101
          // TODO: save ErrorCode
4102
            //return Error(Op3.getStartLoc(),
4103
            //             "expected integer in range [0, 31]");
4104
0
            ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
4105
0
            return true;
4106
0
          }
4107
0
          if (Op4Val < 1 || Op4Val > RegWidth) {
4108
          // TODO: save ErrorCode
4109
            //return Error(Op4.getStartLoc(),
4110
            //             "expected integer in range [1, 32]");
4111
0
            ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
4112
0
            return true;
4113
0
          }
4114
4115
0
          uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4116
4117
0
          if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val) {
4118
          // TODO: save ErrorCode
4119
            //return Error(Op4.getStartLoc(),
4120
            //             "requested extract overflows register");
4121
0
            ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
4122
0
            return true;
4123
0
          }
4124
4125
0
          const MCExpr *NewOp4 =
4126
0
              MCConstantExpr::create(NewOp4Val, getContext());
4127
0
          Operands[4] = AArch64Operand::CreateImm(
4128
0
              NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
4129
0
          if (Tok == "bfxil")
4130
0
            Operands[0] = AArch64Operand::CreateToken(
4131
0
                "bfm", false, Op.getStartLoc(), getContext());
4132
0
          else if (Tok == "sbfx")
4133
0
            Operands[0] = AArch64Operand::CreateToken(
4134
0
                "sbfm", false, Op.getStartLoc(), getContext());
4135
0
          else if (Tok == "ubfx")
4136
0
            Operands[0] = AArch64Operand::CreateToken(
4137
0
                "ubfm", false, Op.getStartLoc(), getContext());
4138
0
          else
4139
0
            llvm_unreachable("No valid mnemonic for alias?");
4140
0
        }
4141
0
      }
4142
0
    }
4143
150
  }
4144
  // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4145
  //        InstAlias can't quite handle this since the reg classes aren't
4146
  //        subclasses.
4147
2.50k
  if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4148
    // The source register can be Wn here, but the matcher expects a
4149
    // GPR64. Twiddle it here if necessary.
4150
0
    AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
4151
0
    if (Op.isReg()) {
4152
0
      unsigned Reg = getXRegFromWReg(Op.getReg());
4153
0
      Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
4154
0
                                              Op.getEndLoc(), getContext());
4155
0
    }
4156
0
  }
4157
  // FIXME: Likewise for sxt[bh] with a Xd dst operand
4158
2.50k
  else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
4159
0
    AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
4160
0
    if (Op.isReg() &&
4161
0
        AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4162
0
            Op.getReg())) {
4163
      // The source register can be Wn here, but the matcher expects a
4164
      // GPR64. Twiddle it here if necessary.
4165
0
      AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
4166
0
      if (Op.isReg()) {
4167
0
        unsigned Reg = getXRegFromWReg(Op.getReg());
4168
0
        Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
4169
0
                                                Op.getEndLoc(), getContext());
4170
0
      }
4171
0
    }
4172
0
  }
4173
  // FIXME: Likewise for uxt[bh] with a Xd dst operand
4174
2.50k
  else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
4175
0
    AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
4176
0
    if (Op.isReg() &&
4177
0
        AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4178
0
            Op.getReg())) {
4179
      // The source register can be Wn here, but the matcher expects a
4180
      // GPR32. Twiddle it here if necessary.
4181
0
      AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
4182
0
      if (Op.isReg()) {
4183
0
        unsigned Reg = getWRegFromXReg(Op.getReg());
4184
0
        Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
4185
0
                                                Op.getEndLoc(), getContext());
4186
0
      }
4187
0
    }
4188
0
  }
4189
4190
  // Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
4191
2.50k
  if (NumOperands == 3 && Tok == "fmov") {
4192
1
    AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
4193
1
    AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
4194
1
    if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
4195
1
      unsigned zreg =
4196
1
          !AArch64MCRegisterClasses[AArch64::FPR64RegClassID].contains(
4197
1
              RegOp.getReg())
4198
1
              ? AArch64::WZR
4199
1
              : AArch64::XZR;
4200
1
      Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
4201
1
                                              Op.getEndLoc(), getContext());
4202
1
    }
4203
1
  }
4204
4205
2.50k
  MCInst Inst(Address);
4206
  // First try to match against the secondary set of tables containing the
4207
  // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4208
2.50k
  unsigned MatchResult =
4209
2.50k
      MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
4210
4211
  // If that fails, try against the alternate table containing long-form NEON:
4212
  // "fadd v0.2s, v1.2s, v2.2s"
4213
2.50k
  if (MatchResult != Match_Success) {
4214
    // But first, save the short-form match result: we can use it in case the
4215
    // long-form match also fails.
4216
332
    auto ShortFormNEONErrorInfo = ErrorInfo;
4217
332
    auto ShortFormNEONMatchResult = MatchResult;
4218
4219
332
    MatchResult =
4220
332
        MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
4221
4222
    // Now, both matches failed, and the long-form match failed on the mnemonic
4223
    // suffix token operand.  The short-form match failure is probably more
4224
    // relevant: use it instead.
4225
332
    if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
4226
7
        Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
4227
1
        ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4228
1
      MatchResult = ShortFormNEONMatchResult;
4229
1
      ErrorInfo = ShortFormNEONErrorInfo;
4230
1
    }
4231
332
  }
4232
4233
  // save the error code
4234
2.50k
  ErrorCode = MatchResult;
4235
4236
2.50k
  switch (MatchResult) {
4237
2.16k
  case Match_Success: {
4238
    // Perform range checking and other semantic validations
4239
2.16k
    SmallVector<SMLoc, 8> OperandLocs;
4240
2.16k
    NumOperands = Operands.size();
4241
5.12k
    for (unsigned i = 1; i < NumOperands; ++i)
4242
2.95k
      OperandLocs.push_back(Operands[i]->getStartLoc());
4243
2.16k
    if (validateInstruction(Inst, OperandLocs))
4244
0
      return true;
4245
4246
2.16k
    Inst.setLoc(IDLoc);
4247
2.16k
    Out.EmitInstruction(Inst, getSTI(), ErrorCode);
4248
2.16k
    if (ErrorCode == 0) {
4249
2.16k
        Address = Inst.getAddress(); // Keystone update address
4250
2.16k
        return false;
4251
2.16k
    } else
4252
0
        return true;
4253
2.16k
  }
4254
0
  case Match_MissingFeature: {
4255
0
    assert(ErrorInfo && "Unknown missing feature!");
4256
    // Special case the error message for the very common case where only
4257
    // a single subtarget feature is missing (neon, e.g.).
4258
0
    std::string Msg = "instruction requires:";
4259
0
    uint64_t Mask = 1;
4260
0
    for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4261
0
      if (ErrorInfo & Mask) {
4262
0
        Msg += " ";
4263
0
        Msg += getSubtargetFeatureName(ErrorInfo & Mask);
4264
0
      }
4265
0
      Mask <<= 1;
4266
0
    }
4267
    //return Error(IDLoc, Msg);
4268
0
    ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
4269
0
    return true;
4270
0
  }
4271
206
  case Match_MnemonicFail:
4272
206
    return showMatchError(IDLoc, MatchResult);
4273
122
  case Match_InvalidOperand: {
4274
122
    SMLoc ErrorLoc = IDLoc;
4275
4276
122
    if (ErrorInfo != ~0ULL) {
4277
122
      if (ErrorInfo >= Operands.size()) {
4278
        //return Error(IDLoc, "too few operands for instruction");
4279
3
        ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
4280
3
        return true;
4281
3
      }
4282
4283
119
      ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
4284
119
      if (ErrorLoc == SMLoc())
4285
0
        ErrorLoc = IDLoc;
4286
119
    }
4287
    // If the match failed on a suffix token operand, tweak the diagnostic
4288
    // accordingly.
4289
119
    if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4290
21
        ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
4291
14
      MatchResult = Match_InvalidSuffix;
4292
4293
119
    return showMatchError(ErrorLoc, MatchResult);
4294
122
  }
4295
0
  case Match_InvalidMemoryIndexed1:
4296
0
  case Match_InvalidMemoryIndexed2:
4297
0
  case Match_InvalidMemoryIndexed4:
4298
0
  case Match_InvalidMemoryIndexed8:
4299
0
  case Match_InvalidMemoryIndexed16:
4300
0
  case Match_InvalidCondCode:
4301
0
  case Match_AddSubRegExtendSmall:
4302
0
  case Match_AddSubRegExtendLarge:
4303
0
  case Match_AddSubSecondSource:
4304
1
  case Match_LogicalSecondSource:
4305
1
  case Match_AddSubRegShift32:
4306
1
  case Match_AddSubRegShift64:
4307
1
  case Match_InvalidMovImm32Shift:
4308
1
  case Match_InvalidMovImm64Shift:
4309
1
  case Match_InvalidFPImm:
4310
1
  case Match_InvalidMemoryWExtend8:
4311
1
  case Match_InvalidMemoryWExtend16:
4312
1
  case Match_InvalidMemoryWExtend32:
4313
1
  case Match_InvalidMemoryWExtend64:
4314
1
  case Match_InvalidMemoryWExtend128:
4315
1
  case Match_InvalidMemoryXExtend8:
4316
1
  case Match_InvalidMemoryXExtend16:
4317
1
  case Match_InvalidMemoryXExtend32:
4318
1
  case Match_InvalidMemoryXExtend64:
4319
1
  case Match_InvalidMemoryXExtend128:
4320
1
  case Match_InvalidMemoryIndexed4SImm7:
4321
1
  case Match_InvalidMemoryIndexed8SImm7:
4322
1
  case Match_InvalidMemoryIndexed16SImm7:
4323
1
  case Match_InvalidMemoryIndexedSImm9:
4324
1
  case Match_InvalidImm0_1:
4325
1
  case Match_InvalidImm0_7:
4326
1
  case Match_InvalidImm0_15:
4327
1
  case Match_InvalidImm0_31:
4328
1
  case Match_InvalidImm0_63:
4329
2
  case Match_InvalidImm0_127:
4330
2
  case Match_InvalidImm0_65535:
4331
2
  case Match_InvalidImm1_8:
4332
2
  case Match_InvalidImm1_16:
4333
2
  case Match_InvalidImm1_32:
4334
2
  case Match_InvalidImm1_64:
4335
2
  case Match_InvalidIndex1:
4336
2
  case Match_InvalidIndexB:
4337
2
  case Match_InvalidIndexH:
4338
2
  case Match_InvalidIndexS:
4339
2
  case Match_InvalidIndexD:
4340
2
  case Match_InvalidLabel:
4341
4
  case Match_MSR:
4342
4
  case Match_MRS: {
4343
4
    if (ErrorInfo >= Operands.size()) {
4344
      //return Error(IDLoc, "too few operands for instruction");
4345
0
      ErrorCode = KS_ERR_ASM_INVALIDOPERAND;
4346
0
      return true;
4347
0
    }
4348
    // Any time we get here, there's nothing fancy to do. Just get the
4349
    // operand SMLoc and display the diagnostic.
4350
4
    SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
4351
4
    if (ErrorLoc == SMLoc())
4352
0
      ErrorLoc = IDLoc;
4353
4
    return showMatchError(ErrorLoc, MatchResult);
4354
4
  }
4355
2.50k
  }
4356
4357
2.50k
  llvm_unreachable("Implement any new match types added!");
4358
2.50k
}
4359
4360
/// ParseDirective parses the arm specific directives
4361
102k
bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
4362
102k
  const MCObjectFileInfo::Environment Format =
4363
102k
    getContext().getObjectFileInfo()->getObjectFileType();
4364
102k
  bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4365
102k
  bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
4366
4367
102k
  StringRef IDVal = DirectiveID.getIdentifier();
4368
102k
  SMLoc Loc = DirectiveID.getLoc();
4369
102k
  if (IDVal == ".hword")
4370
0
    return parseDirectiveWord(2, Loc);
4371
102k
  if (IDVal == ".word")
4372
17.2k
    return parseDirectiveWord(4, Loc);
4373
85.0k
  if (IDVal == ".xword")
4374
0
    return parseDirectiveWord(8, Loc);
4375
85.0k
  if (IDVal == ".tlsdesccall")
4376
0
    return parseDirectiveTLSDescCall(Loc);
4377
85.0k
  if (IDVal == ".ltorg" || IDVal == ".pool")
4378
1
    return parseDirectiveLtorg(Loc);
4379
85.0k
  if (IDVal == ".unreq")
4380
99
    return parseDirectiveUnreq(Loc);
4381
4382
84.9k
  if (!IsMachO && !IsCOFF) {
4383
84.9k
    if (IDVal == ".inst")
4384
267
      return parseDirectiveInst(Loc);
4385
84.9k
  }
4386
4387
84.6k
  return parseDirectiveLOH(IDVal, Loc);
4388
84.9k
}
4389
4390
/// parseDirectiveWord
4391
///  ::= .word [ expression (, expression)* ]
4392
bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L)
4393
17.2k
{
4394
17.2k
  MCAsmParser &Parser = getParser();
4395
17.2k
  if (getLexer().isNot(AsmToken::EndOfStatement)) {
4396
55.4k
    for (;;) {
4397
55.4k
      const MCExpr *Value;
4398
55.4k
      if (getParser().parseExpression(Value))
4399
617
        return true;
4400
4401
54.8k
      getParser().getStreamer().EmitValue(Value, Size, L);
4402
4403
54.8k
      if (getLexer().is(AsmToken::EndOfStatement))
4404
13.4k
        break;
4405
4406
      // FIXME: Improve diagnostic.
4407
41.3k
      if (getLexer().isNot(AsmToken::Comma))
4408
        //return Error(L, "unexpected token in directive");
4409
2.17k
        return true;
4410
39.1k
      Parser.Lex();
4411
39.1k
    }
4412
16.2k
  }
4413
4414
14.4k
  Parser.Lex();
4415
14.4k
  return false;
4416
17.2k
}
4417
4418
/// parseDirectiveInst
4419
///  ::= .inst opcode [, ...]
4420
bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc)
4421
267
{
4422
267
  MCAsmParser &Parser = getParser();
4423
267
  if (getLexer().is(AsmToken::EndOfStatement)) {
4424
1
    Parser.eatToEndOfStatement();
4425
    //Error(Loc, "expected expression following directive");
4426
1
    return false;
4427
1
  }
4428
4429
286
  for (;;) {
4430
286
    const MCExpr *Expr;
4431
4432
286
    if (getParser().parseExpression(Expr)) {
4433
      //Error(Loc, "expected expression");
4434
1
      return false;
4435
1
    }
4436
4437
285
    const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
4438
285
    if (!Value) {
4439
      //Error(Loc, "expected constant expression");
4440
203
      return false;
4441
203
    }
4442
4443
82
    getTargetStreamer().emitInst(Value->getValue());
4444
4445
82
    if (getLexer().is(AsmToken::EndOfStatement))
4446
20
      break;
4447
4448
62
    if (getLexer().isNot(AsmToken::Comma)) {
4449
      //Error(Loc, "unexpected token in directive");
4450
42
      return false;
4451
42
    }
4452
4453
20
    Parser.Lex(); // Eat comma.
4454
20
  }
4455
4456
20
  Parser.Lex();
4457
20
  return false;
4458
266
}
4459
4460
// parseDirectiveTLSDescCall:
4461
//   ::= .tlsdesccall symbol
4462
0
bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4463
0
  StringRef Name;
4464
0
  if (getParser().parseIdentifier(Name))
4465
    //return Error(L, "expected symbol after directive");
4466
0
    return true;
4467
4468
0
  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4469
0
  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4470
0
  Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
4471
4472
0
  MCInst Inst;
4473
0
  Inst.setOpcode(AArch64::TLSDESCCALL);
4474
0
  Inst.addOperand(MCOperand::createExpr(Expr));
4475
4476
0
  unsigned int KsError;
4477
0
  getParser().getStreamer().EmitInstruction(Inst, getSTI(), KsError);
4478
0
  return false;
4479
0
}
4480
4481
/// ::= .loh <lohName | lohId> label1, ..., labelN
4482
/// The number of arguments depends on the loh identifier.
4483
bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc)
4484
84.6k
{
4485
84.6k
  if (IDVal != MCLOHDirectiveName())
4486
84.5k
    return true;
4487
62
  MCLOHType Kind;
4488
62
  if (getParser().getTok().isNot(AsmToken::Identifier)) {
4489
61
    if (getParser().getTok().isNot(AsmToken::Integer))
4490
      //return TokError("expected an identifier or a number in directive");
4491
0
      return true;
4492
    // We successfully get a numeric value for the identifier.
4493
    // Check if it is valid.
4494
61
    bool valid;
4495
61
    int64_t Id = getParser().getTok().getIntVal(valid);
4496
61
    if (!valid)
4497
0
      return true;
4498
61
    if (Id <= -1U && !isValidMCLOHType(Id))
4499
      //return TokError("invalid numeric identifier in directive");
4500
0
      return true;
4501
61
    Kind = (MCLOHType)Id;
4502
61
  } else {
4503
1
    StringRef Name = getTok().getIdentifier();
4504
    // We successfully parse an identifier.
4505
    // Check if it is a recognized one.
4506
1
    int Id = MCLOHNameToId(Name);
4507
4508
1
    if (Id == -1)
4509
      //return TokError("invalid identifier in directive");
4510
1
      return true;
4511
0
    Kind = (MCLOHType)Id;
4512
0
  }
4513
  // Consume the identifier.
4514
61
  Lex();
4515
  // Get the number of arguments of this LOH.
4516
61
  int NbArgs = MCLOHIdToNbArgs(Kind);
4517
4518
61
  assert(NbArgs != -1 && "Invalid number of arguments");
4519
4520
61
  SmallVector<MCSymbol *, 3> Args;
4521
116
  for (int Idx = 0; Idx < NbArgs; ++Idx) {
4522
116
    StringRef Name;
4523
116
    if (getParser().parseIdentifier(Name))
4524
      //return TokError("expected identifier in directive");
4525
6
      return true;
4526
110
    Args.push_back(getContext().getOrCreateSymbol(Name));
4527
4528
110
    if (Idx + 1 == NbArgs)
4529
14
      break;
4530
96
    if (getLexer().isNot(AsmToken::Comma))
4531
      //return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
4532
41
      return true;
4533
55
    Lex();
4534
55
  }
4535
14
  if (getLexer().isNot(AsmToken::EndOfStatement))
4536
    //return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
4537
0
    return true;
4538
4539
14
  getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4540
14
  return false;
4541
14
}
4542
4543
/// parseDirectiveLtorg
4544
///  ::= .ltorg | .pool
4545
1
bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
4546
1
  getTargetStreamer().emitCurrentConstantPool();
4547
1
  return false;
4548
1
}
4549
4550
/// parseDirectiveReq
4551
///  ::= name .req registername
4552
bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L)
4553
0
{
4554
0
  MCAsmParser &Parser = getParser();
4555
0
  Parser.Lex(); // Eat the '.req' token.
4556
  //SMLoc SRegLoc = getLoc();
4557
0
  unsigned RegNum = tryParseRegister();
4558
0
  bool IsVector = false;
4559
4560
0
  if (RegNum == static_cast<unsigned>(-1)) {
4561
0
    StringRef Kind;
4562
0
    RegNum = tryMatchVectorRegister(Kind, false);
4563
0
    if (!Kind.empty()) {
4564
      //Error(SRegLoc, "vector register without type specifier expected");
4565
0
      return false;
4566
0
    }
4567
0
    IsVector = true;
4568
0
  }
4569
4570
0
  if (RegNum == static_cast<unsigned>(-1)) {
4571
0
    Parser.eatToEndOfStatement();
4572
    //Error(SRegLoc, "register name or alias expected");
4573
0
    return false;
4574
0
  }
4575
4576
  // Shouldn't be anything else.
4577
0
  if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4578
    //Error(Parser.getTok().getLoc(), "unexpected input in .req directive");
4579
0
    Parser.eatToEndOfStatement();
4580
0
    return false;
4581
0
  }
4582
4583
0
  Parser.Lex(); // Consume the EndOfStatement
4584
4585
0
  auto pair = std::make_pair(IsVector, RegNum);
4586
0
  if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
4587
0
    Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4588
4589
0
  return true;
4590
0
}
4591
4592
/// parseDirectiveUneq
4593
///  ::= .unreq registername
4594
bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L)
4595
99
{
4596
99
  MCAsmParser &Parser = getParser();
4597
99
  if (Parser.getTok().isNot(AsmToken::Identifier)) {
4598
    //Error(Parser.getTok().getLoc(), "unexpected input in .unreq directive.");
4599
0
    Parser.eatToEndOfStatement();
4600
0
    return false;
4601
0
  }
4602
99
  RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4603
99
  Parser.Lex(); // Eat the identifier.
4604
99
  return false;
4605
99
}
4606
4607
bool
4608
AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4609
                                    AArch64MCExpr::VariantKind &ELFRefKind,
4610
                                    MCSymbolRefExpr::VariantKind &DarwinRefKind,
4611
14
                                    int64_t &Addend) {
4612
14
  ELFRefKind = AArch64MCExpr::VK_INVALID;
4613
14
  DarwinRefKind = MCSymbolRefExpr::VK_None;
4614
14
  Addend = 0;
4615
4616
14
  if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4617
0
    ELFRefKind = AE->getKind();
4618
0
    Expr = AE->getSubExpr();
4619
0
  }
4620
4621
14
  const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4622
14
  if (SE) {
4623
    // It's a simple symbol reference with no addend.
4624
1
    DarwinRefKind = SE->getKind();
4625
1
    return true;
4626
1
  }
4627
4628
13
  const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4629
13
  if (!BE)
4630
13
    return false;
4631
4632
0
  SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4633
0
  if (!SE)
4634
0
    return false;
4635
0
  DarwinRefKind = SE->getKind();
4636
4637
0
  if (BE->getOpcode() != MCBinaryExpr::Add &&
4638
0
      BE->getOpcode() != MCBinaryExpr::Sub)
4639
0
    return false;
4640
4641
  // See if the addend is is a constant, otherwise there's more going
4642
  // on here than we can deal with.
4643
0
  auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4644
0
  if (!AddendExpr)
4645
0
    return false;
4646
4647
0
  Addend = AddendExpr->getValue();
4648
0
  if (BE->getOpcode() == MCBinaryExpr::Sub)
4649
0
    Addend = -Addend;
4650
4651
  // It's some symbol reference + a constant addend, but really
4652
  // shouldn't use both Darwin and ELF syntax.
4653
0
  return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4654
0
         DarwinRefKind == MCSymbolRefExpr::VK_None;
4655
0
}
4656
4657
/// Force static initialization.
4658
25
extern "C" void LLVMInitializeAArch64AsmParser() {
4659
25
  RegisterMCAsmParser<AArch64AsmParser> X(TheAArch64leTarget);
4660
25
  RegisterMCAsmParser<AArch64AsmParser> Y(TheAArch64beTarget);
4661
25
  RegisterMCAsmParser<AArch64AsmParser> Z(TheARM64Target);
4662
25
}
4663
4664
#define GET_REGISTER_MATCHER
4665
#define GET_SUBTARGET_FEATURE_NAME
4666
#define GET_MATCHER_IMPLEMENTATION
4667
#include "AArch64GenAsmMatcher.inc"
4668
4669
// Define this matcher function after the auto-generated include so we
4670
// have the match class enum definitions.
4671
unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
4672
1.56k
                                                      unsigned Kind) {
4673
1.56k
  AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
4674
  // If the kind is a token for a literal immediate, check if our asm
4675
  // operand matches. This is for InstAliases which have a fixed-value
4676
  // immediate in the syntax.
4677
1.56k
  int64_t ExpectedVal;
4678
1.56k
  switch (Kind) {
4679
1.56k
  default:
4680
1.56k
    return Match_InvalidOperand;
4681
0
  case MCK__35_0:
4682
0
    ExpectedVal = 0;
4683
0
    break;
4684
0
  case MCK__35_1:
4685
0
    ExpectedVal = 1;
4686
0
    break;
4687
0
  case MCK__35_12:
4688
0
    ExpectedVal = 12;
4689
0
    break;
4690
0
  case MCK__35_16:
4691
0
    ExpectedVal = 16;
4692
0
    break;
4693
0
  case MCK__35_2:
4694
0
    ExpectedVal = 2;
4695
0
    break;
4696
0
  case MCK__35_24:
4697
0
    ExpectedVal = 24;
4698
0
    break;
4699
0
  case MCK__35_3:
4700
0
    ExpectedVal = 3;
4701
0
    break;
4702
0
  case MCK__35_32:
4703
0
    ExpectedVal = 32;
4704
0
    break;
4705
0
  case MCK__35_4:
4706
0
    ExpectedVal = 4;
4707
0
    break;
4708
0
  case MCK__35_48:
4709
0
    ExpectedVal = 48;
4710
0
    break;
4711
0
  case MCK__35_6:
4712
0
    ExpectedVal = 6;
4713
0
    break;
4714
0
  case MCK__35_64:
4715
0
    ExpectedVal = 64;
4716
0
    break;
4717
0
  case MCK__35_8:
4718
0
    ExpectedVal = 8;
4719
0
    break;
4720
1.56k
  }
4721
0
  if (!Op.isImm())
4722
0
    return Match_InvalidOperand;
4723
0
  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
4724
0
  if (!CE)
4725
0
    return Match_InvalidOperand;
4726
0
  if (CE->getValue() == ExpectedVal)
4727
0
    return Match_Success;
4728
0
  return Match_InvalidOperand;
4729
0
}
4730
4731
4732
AArch64AsmParser::OperandMatchResultTy
4733
AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands)
4734
0
{
4735
0
  SMLoc S = getLoc();
4736
4737
0
  if (getParser().getTok().isNot(AsmToken::Identifier)) {
4738
    //Error(S, "expected register");
4739
0
    return MatchOperand_ParseFail;
4740
0
  }
4741
4742
0
  int FirstReg = tryParseRegister();
4743
0
  if (FirstReg == -1) {
4744
0
    return MatchOperand_ParseFail;
4745
0
  }
4746
0
  const MCRegisterClass &WRegClass =
4747
0
      AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4748
0
  const MCRegisterClass &XRegClass =
4749
0
      AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4750
4751
0
  bool isXReg = XRegClass.contains(FirstReg),
4752
0
       isWReg = WRegClass.contains(FirstReg);
4753
0
  if (!isXReg && !isWReg) {
4754
    //Error(S, "expected first even register of a "
4755
    //         "consecutive same-size even/odd register pair");
4756
0
    return MatchOperand_ParseFail;
4757
0
  }
4758
4759
0
  const MCRegisterInfo *RI = getContext().getRegisterInfo();
4760
0
  unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4761
4762
0
  if (FirstEncoding & 0x1) {
4763
    //Error(S, "expected first even register of a "
4764
    //         "consecutive same-size even/odd register pair");
4765
0
    return MatchOperand_ParseFail;
4766
0
  }
4767
4768
  //SMLoc M = getLoc();
4769
0
  if (getParser().getTok().isNot(AsmToken::Comma)) {
4770
    //Error(M, "expected comma");
4771
0
    return MatchOperand_ParseFail;
4772
0
  }
4773
  // Eat the comma
4774
0
  getParser().Lex();
4775
4776
  //SMLoc E = getLoc();
4777
0
  int SecondReg = tryParseRegister();
4778
0
  if (SecondReg ==-1) {
4779
0
    return MatchOperand_ParseFail;
4780
0
  }
4781
4782
0
 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
4783
0
      (isXReg && !XRegClass.contains(SecondReg)) ||
4784
0
      (isWReg && !WRegClass.contains(SecondReg))) {
4785
    //Error(E,"expected second odd register of a "
4786
    //         "consecutive same-size even/odd register pair");
4787
0
    return MatchOperand_ParseFail;
4788
0
  }
4789
  
4790
0
  unsigned Pair = 0;
4791
0
  if(isXReg) {
4792
0
    Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4793
0
           &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4794
0
  } else {
4795
0
    Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4796
0
           &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4797
0
  }
4798
4799
0
  Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(),
4800
0
      getContext()));
4801
4802
0
  return MatchOperand_Success;
4803
0
}