1303231Sdim//===-- LanaiAsmParser.cpp - Parse Lanai assembly to MCInst instructions --===//
2303231Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6303231Sdim//
7303231Sdim//===----------------------------------------------------------------------===//
8303231Sdim
9314564Sdim#include "LanaiAluCode.h"
10314564Sdim#include "LanaiCondCode.h"
11353358Sdim#include "LanaiInstrInfo.h"
12303231Sdim#include "MCTargetDesc/LanaiMCExpr.h"
13353358Sdim#include "TargetInfo/LanaiTargetInfo.h"
14303231Sdim#include "llvm/ADT/STLExtras.h"
15314564Sdim#include "llvm/ADT/StringRef.h"
16314564Sdim#include "llvm/ADT/StringSwitch.h"
17303231Sdim#include "llvm/MC/MCContext.h"
18303231Sdim#include "llvm/MC/MCExpr.h"
19303231Sdim#include "llvm/MC/MCInst.h"
20303231Sdim#include "llvm/MC/MCParser/MCAsmLexer.h"
21314564Sdim#include "llvm/MC/MCParser/MCAsmParser.h"
22303231Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23303231Sdim#include "llvm/MC/MCParser/MCTargetAsmParser.h"
24303231Sdim#include "llvm/MC/MCStreamer.h"
25303231Sdim#include "llvm/MC/MCSubtargetInfo.h"
26303231Sdim#include "llvm/MC/MCSymbol.h"
27314564Sdim#include "llvm/Support/Casting.h"
28314564Sdim#include "llvm/Support/ErrorHandling.h"
29303231Sdim#include "llvm/Support/MathExtras.h"
30314564Sdim#include "llvm/Support/SMLoc.h"
31321369Sdim#include "llvm/Support/TargetRegistry.h"
32314564Sdim#include "llvm/Support/raw_ostream.h"
33314564Sdim#include <algorithm>
34314564Sdim#include <cassert>
35314564Sdim#include <cstddef>
36314564Sdim#include <cstdint>
37314564Sdim#include <memory>
38303231Sdim
39327952Sdimusing namespace llvm;
40314564Sdim
41314564Sdim// Auto-generated by TableGen
42314564Sdimstatic unsigned MatchRegisterName(StringRef Name);
43314564Sdim
44303231Sdimnamespace {
45314564Sdim
46303231Sdimstruct LanaiOperand;
47303231Sdim
48303231Sdimclass LanaiAsmParser : public MCTargetAsmParser {
49303231Sdim  // Parse operands
50303231Sdim  std::unique_ptr<LanaiOperand> parseRegister();
51303231Sdim
52303231Sdim  std::unique_ptr<LanaiOperand> parseImmediate();
53303231Sdim
54303231Sdim  std::unique_ptr<LanaiOperand> parseIdentifier();
55303231Sdim
56303231Sdim  unsigned parseAluOperator(bool PreOp, bool PostOp);
57303231Sdim
58303231Sdim  // Split the mnemonic stripping conditional code and quantifiers
59303231Sdim  StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
60303231Sdim                          OperandVector *Operands);
61303231Sdim
62303231Sdim  bool parsePrePost(StringRef Type, int *OffsetValue);
63303231Sdim
64303231Sdim  bool ParseDirective(AsmToken DirectiveID) override;
65303231Sdim
66303231Sdim  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
67303231Sdim                        SMLoc NameLoc, OperandVector &Operands) override;
68303231Sdim
69303231Sdim  bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override;
70303231Sdim
71303231Sdim  bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
72303231Sdim                               OperandVector &Operands, MCStreamer &Out,
73303231Sdim                               uint64_t &ErrorInfo,
74303231Sdim                               bool MatchingInlineAsm) override;
75303231Sdim
76303231Sdim// Auto-generated instruction matching functions
77303231Sdim#define GET_ASSEMBLER_HEADER
78303231Sdim#include "LanaiGenAsmMatcher.inc"
79303231Sdim
80303231Sdim  OperandMatchResultTy parseOperand(OperandVector *Operands,
81303231Sdim                                    StringRef Mnemonic);
82303231Sdim
83303231Sdim  OperandMatchResultTy parseMemoryOperand(OperandVector &Operands);
84303231Sdim
85303231Sdimpublic:
86303231Sdim  LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
87303231Sdim                 const MCInstrInfo &MII, const MCTargetOptions &Options)
88327952Sdim      : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
89303231Sdim        Lexer(Parser.getLexer()), SubtargetInfo(STI) {
90303231Sdim    setAvailableFeatures(
91303231Sdim        ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
92303231Sdim  }
93303231Sdim
94303231Sdimprivate:
95303231Sdim  MCAsmParser &Parser;
96303231Sdim  MCAsmLexer &Lexer;
97303231Sdim
98303231Sdim  const MCSubtargetInfo &SubtargetInfo;
99303231Sdim};
100303231Sdim
101303231Sdim// LanaiOperand - Instances of this class represented a parsed machine
102303231Sdim// instruction
103303231Sdimstruct LanaiOperand : public MCParsedAsmOperand {
104303231Sdim  enum KindTy {
105303231Sdim    TOKEN,
106303231Sdim    REGISTER,
107303231Sdim    IMMEDIATE,
108303231Sdim    MEMORY_IMM,
109303231Sdim    MEMORY_REG_IMM,
110303231Sdim    MEMORY_REG_REG,
111303231Sdim  } Kind;
112303231Sdim
113303231Sdim  SMLoc StartLoc, EndLoc;
114303231Sdim
115303231Sdim  struct Token {
116303231Sdim    const char *Data;
117303231Sdim    unsigned Length;
118303231Sdim  };
119303231Sdim
120303231Sdim  struct RegOp {
121303231Sdim    unsigned RegNum;
122303231Sdim  };
123303231Sdim
124303231Sdim  struct ImmOp {
125303231Sdim    const MCExpr *Value;
126303231Sdim  };
127303231Sdim
128303231Sdim  struct MemOp {
129303231Sdim    unsigned BaseReg;
130303231Sdim    unsigned OffsetReg;
131303231Sdim    unsigned AluOp;
132303231Sdim    const MCExpr *Offset;
133303231Sdim  };
134303231Sdim
135303231Sdim  union {
136303231Sdim    struct Token Tok;
137303231Sdim    struct RegOp Reg;
138303231Sdim    struct ImmOp Imm;
139303231Sdim    struct MemOp Mem;
140303231Sdim  };
141303231Sdim
142303231Sdim  explicit LanaiOperand(KindTy Kind) : MCParsedAsmOperand(), Kind(Kind) {}
143303231Sdim
144303231Sdimpublic:
145303231Sdim  // The functions below are used by the autogenerated ASM matcher and hence to
146303231Sdim  // be of the form expected.
147303231Sdim
148303231Sdim  // getStartLoc - Gets location of the first token of this operand
149303231Sdim  SMLoc getStartLoc() const override { return StartLoc; }
150303231Sdim
151303231Sdim  // getEndLoc - Gets location of the last token of this operand
152303231Sdim  SMLoc getEndLoc() const override { return EndLoc; }
153303231Sdim
154303231Sdim  unsigned getReg() const override {
155303231Sdim    assert(isReg() && "Invalid type access!");
156303231Sdim    return Reg.RegNum;
157303231Sdim  }
158303231Sdim
159303231Sdim  const MCExpr *getImm() const {
160303231Sdim    assert(isImm() && "Invalid type access!");
161303231Sdim    return Imm.Value;
162303231Sdim  }
163303231Sdim
164303231Sdim  StringRef getToken() const {
165303231Sdim    assert(isToken() && "Invalid type access!");
166303231Sdim    return StringRef(Tok.Data, Tok.Length);
167303231Sdim  }
168303231Sdim
169303231Sdim  unsigned getMemBaseReg() const {
170303231Sdim    assert(isMem() && "Invalid type access!");
171303231Sdim    return Mem.BaseReg;
172303231Sdim  }
173303231Sdim
174303231Sdim  unsigned getMemOffsetReg() const {
175303231Sdim    assert(isMem() && "Invalid type access!");
176303231Sdim    return Mem.OffsetReg;
177303231Sdim  }
178303231Sdim
179303231Sdim  const MCExpr *getMemOffset() const {
180303231Sdim    assert(isMem() && "Invalid type access!");
181303231Sdim    return Mem.Offset;
182303231Sdim  }
183303231Sdim
184303231Sdim  unsigned getMemOp() const {
185303231Sdim    assert(isMem() && "Invalid type access!");
186303231Sdim    return Mem.AluOp;
187303231Sdim  }
188303231Sdim
189303231Sdim  // Functions for testing operand type
190303231Sdim  bool isReg() const override { return Kind == REGISTER; }
191303231Sdim
192303231Sdim  bool isImm() const override { return Kind == IMMEDIATE; }
193303231Sdim
194303231Sdim  bool isMem() const override {
195303231Sdim    return isMemImm() || isMemRegImm() || isMemRegReg();
196303231Sdim  }
197303231Sdim
198303231Sdim  bool isMemImm() const { return Kind == MEMORY_IMM; }
199303231Sdim
200303231Sdim  bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
201303231Sdim
202303231Sdim  bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
203303231Sdim
204303231Sdim  bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
205303231Sdim
206303231Sdim  bool isToken() const override { return Kind == TOKEN; }
207303231Sdim
208303231Sdim  bool isBrImm() {
209303231Sdim    if (!isImm())
210303231Sdim      return false;
211303231Sdim
212303231Sdim    // Constant case
213303231Sdim    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value);
214303231Sdim    if (!MCE)
215303231Sdim      return true;
216303231Sdim    int64_t Value = MCE->getValue();
217303231Sdim    // Check if value fits in 25 bits with 2 least significant bits 0.
218303231Sdim    return isShiftedUInt<23, 2>(static_cast<int32_t>(Value));
219303231Sdim  }
220303231Sdim
221303231Sdim  bool isBrTarget() { return isBrImm() || isToken(); }
222303231Sdim
223303231Sdim  bool isCallTarget() { return isImm() || isToken(); }
224303231Sdim
225303231Sdim  bool isHiImm16() {
226303231Sdim    if (!isImm())
227303231Sdim      return false;
228303231Sdim
229303231Sdim    // Constant case
230303231Sdim    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
231303231Sdim      int64_t Value = ConstExpr->getValue();
232303231Sdim      return Value != 0 && isShiftedUInt<16, 16>(Value);
233303231Sdim    }
234303231Sdim
235303231Sdim    // Symbolic reference expression
236303231Sdim    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
237303231Sdim      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
238303231Sdim
239303231Sdim    // Binary expression
240303231Sdim    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
241303231Sdim      if (const LanaiMCExpr *SymbolRefExpr =
242303231Sdim              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
243303231Sdim        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
244303231Sdim
245303231Sdim    return false;
246303231Sdim  }
247303231Sdim
248303231Sdim  bool isHiImm16And() {
249303231Sdim    if (!isImm())
250303231Sdim      return false;
251303231Sdim
252303231Sdim    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
253303231Sdim    if (ConstExpr) {
254303231Sdim      int64_t Value = ConstExpr->getValue();
255303231Sdim      // Check if in the form 0xXYZWffff
256303231Sdim      return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);
257303231Sdim    }
258303231Sdim    return false;
259303231Sdim  }
260303231Sdim
261303231Sdim  bool isLoImm16() {
262303231Sdim    if (!isImm())
263303231Sdim      return false;
264303231Sdim
265303231Sdim    // Constant case
266303231Sdim    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
267303231Sdim      int64_t Value = ConstExpr->getValue();
268303231Sdim      // Check if value fits in 16 bits
269303231Sdim      return isUInt<16>(static_cast<int32_t>(Value));
270303231Sdim    }
271303231Sdim
272303231Sdim    // Symbolic reference expression
273303231Sdim    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
274303231Sdim      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
275303231Sdim
276303231Sdim    // Binary expression
277303231Sdim    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
278303231Sdim      if (const LanaiMCExpr *SymbolRefExpr =
279303231Sdim              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
280303231Sdim        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
281303231Sdim
282303231Sdim    return false;
283303231Sdim  }
284303231Sdim
285303231Sdim  bool isLoImm16Signed() {
286303231Sdim    if (!isImm())
287303231Sdim      return false;
288303231Sdim
289303231Sdim    // Constant case
290303231Sdim    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
291303231Sdim      int64_t Value = ConstExpr->getValue();
292303231Sdim      // Check if value fits in 16 bits or value of the form 0xffffxyzw
293303231Sdim      return isInt<16>(static_cast<int32_t>(Value));
294303231Sdim    }
295303231Sdim
296303231Sdim    // Symbolic reference expression
297303231Sdim    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
298303231Sdim      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
299303231Sdim
300303231Sdim    // Binary expression
301303231Sdim    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
302303231Sdim      if (const LanaiMCExpr *SymbolRefExpr =
303303231Sdim              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
304303231Sdim        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
305303231Sdim
306303231Sdim    return false;
307303231Sdim  }
308303231Sdim
309303231Sdim  bool isLoImm16And() {
310303231Sdim    if (!isImm())
311303231Sdim      return false;
312303231Sdim
313303231Sdim    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
314303231Sdim    if (ConstExpr) {
315303231Sdim      int64_t Value = ConstExpr->getValue();
316303231Sdim      // Check if in the form 0xffffXYZW
317303231Sdim      return ((Value & ~0xffff) == 0xffff0000);
318303231Sdim    }
319303231Sdim    return false;
320303231Sdim  }
321303231Sdim
322303231Sdim  bool isImmShift() {
323303231Sdim    if (!isImm())
324303231Sdim      return false;
325303231Sdim
326303231Sdim    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
327303231Sdim    if (!ConstExpr)
328303231Sdim      return false;
329303231Sdim    int64_t Value = ConstExpr->getValue();
330303231Sdim    return (Value >= -31) && (Value <= 31);
331303231Sdim  }
332303231Sdim
333303231Sdim  bool isLoImm21() {
334303231Sdim    if (!isImm())
335303231Sdim      return false;
336303231Sdim
337303231Sdim    // Constant case
338303231Sdim    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
339303231Sdim      int64_t Value = ConstExpr->getValue();
340303231Sdim      return isUInt<21>(Value);
341303231Sdim    }
342303231Sdim
343303231Sdim    // Symbolic reference expression
344303231Sdim    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
345303231Sdim      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
346303231Sdim    if (const MCSymbolRefExpr *SymbolRefExpr =
347303231Sdim            dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
348303231Sdim      return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
349303231Sdim    }
350303231Sdim
351303231Sdim    // Binary expression
352303231Sdim    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
353303231Sdim      if (const LanaiMCExpr *SymbolRefExpr =
354303231Sdim              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
355303231Sdim        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
356303231Sdim      if (const MCSymbolRefExpr *SymbolRefExpr =
357303231Sdim              dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
358303231Sdim        return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
359303231Sdim    }
360303231Sdim
361303231Sdim    return false;
362303231Sdim  }
363303231Sdim
364303231Sdim  bool isImm10() {
365303231Sdim    if (!isImm())
366303231Sdim      return false;
367303231Sdim
368303231Sdim    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
369303231Sdim    if (!ConstExpr)
370303231Sdim      return false;
371303231Sdim    int64_t Value = ConstExpr->getValue();
372303231Sdim    return isInt<10>(Value);
373303231Sdim  }
374303231Sdim
375303231Sdim  bool isCondCode() {
376303231Sdim    if (!isImm())
377303231Sdim      return false;
378303231Sdim
379303231Sdim    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
380303231Sdim    if (!ConstExpr)
381303231Sdim      return false;
382303231Sdim    uint64_t Value = ConstExpr->getValue();
383303231Sdim    // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the
384303231Sdim    // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then
385303231Sdim    // value corresponds to a valid condition code.
386303231Sdim    return Value < LPCC::UNKNOWN;
387303231Sdim  }
388303231Sdim
389303231Sdim  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
390303231Sdim    // Add as immediates where possible. Null MCExpr = 0
391303231Sdim    if (Expr == nullptr)
392303231Sdim      Inst.addOperand(MCOperand::createImm(0));
393303231Sdim    else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
394303231Sdim      Inst.addOperand(
395303231Sdim          MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
396303231Sdim    else
397303231Sdim      Inst.addOperand(MCOperand::createExpr(Expr));
398303231Sdim  }
399303231Sdim
400303231Sdim  void addRegOperands(MCInst &Inst, unsigned N) const {
401303231Sdim    assert(N == 1 && "Invalid number of operands!");
402303231Sdim    Inst.addOperand(MCOperand::createReg(getReg()));
403303231Sdim  }
404303231Sdim
405303231Sdim  void addImmOperands(MCInst &Inst, unsigned N) const {
406303231Sdim    assert(N == 1 && "Invalid number of operands!");
407303231Sdim    addExpr(Inst, getImm());
408303231Sdim  }
409303231Sdim
410303231Sdim  void addBrTargetOperands(MCInst &Inst, unsigned N) const {
411303231Sdim    assert(N == 1 && "Invalid number of operands!");
412303231Sdim    addExpr(Inst, getImm());
413303231Sdim  }
414303231Sdim
415303231Sdim  void addCallTargetOperands(MCInst &Inst, unsigned N) const {
416303231Sdim    assert(N == 1 && "Invalid number of operands!");
417303231Sdim    addExpr(Inst, getImm());
418303231Sdim  }
419303231Sdim
420303231Sdim  void addCondCodeOperands(MCInst &Inst, unsigned N) const {
421303231Sdim    assert(N == 1 && "Invalid number of operands!");
422303231Sdim    addExpr(Inst, getImm());
423303231Sdim  }
424303231Sdim
425303231Sdim  void addMemImmOperands(MCInst &Inst, unsigned N) const {
426303231Sdim    assert(N == 1 && "Invalid number of operands!");
427303231Sdim    const MCExpr *Expr = getMemOffset();
428303231Sdim    addExpr(Inst, Expr);
429303231Sdim  }
430303231Sdim
431303231Sdim  void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
432303231Sdim    assert(N == 3 && "Invalid number of operands!");
433303231Sdim    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
434303231Sdim    const MCExpr *Expr = getMemOffset();
435303231Sdim    addExpr(Inst, Expr);
436303231Sdim    Inst.addOperand(MCOperand::createImm(getMemOp()));
437303231Sdim  }
438303231Sdim
439303231Sdim  void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
440303231Sdim    assert(N == 3 && "Invalid number of operands!");
441303231Sdim    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
442303231Sdim    assert(getMemOffsetReg() != 0 && "Invalid offset");
443303231Sdim    Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
444303231Sdim    Inst.addOperand(MCOperand::createImm(getMemOp()));
445303231Sdim  }
446303231Sdim
447303231Sdim  void addMemSplsOperands(MCInst &Inst, unsigned N) const {
448303231Sdim    if (isMemRegImm())
449303231Sdim      addMemRegImmOperands(Inst, N);
450303231Sdim    if (isMemRegReg())
451303231Sdim      addMemRegRegOperands(Inst, N);
452303231Sdim  }
453303231Sdim
454303231Sdim  void addImmShiftOperands(MCInst &Inst, unsigned N) const {
455303231Sdim    assert(N == 1 && "Invalid number of operands!");
456303231Sdim    addExpr(Inst, getImm());
457303231Sdim  }
458303231Sdim
459303231Sdim  void addImm10Operands(MCInst &Inst, unsigned N) const {
460303231Sdim    assert(N == 1 && "Invalid number of operands!");
461303231Sdim    addExpr(Inst, getImm());
462303231Sdim  }
463303231Sdim
464303231Sdim  void addLoImm16Operands(MCInst &Inst, unsigned N) const {
465303231Sdim    assert(N == 1 && "Invalid number of operands!");
466303231Sdim    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
467303231Sdim      Inst.addOperand(
468303231Sdim          MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
469303231Sdim    else if (isa<LanaiMCExpr>(getImm())) {
470303231Sdim#ifndef NDEBUG
471303231Sdim      const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
472360784Sdim      assert(SymbolRefExpr &&
473360784Sdim             SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
474303231Sdim#endif
475303231Sdim      Inst.addOperand(MCOperand::createExpr(getImm()));
476303231Sdim    } else if (isa<MCBinaryExpr>(getImm())) {
477303231Sdim#ifndef NDEBUG
478303231Sdim      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
479360784Sdim      assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
480341825Sdim             cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
481303231Sdim                 LanaiMCExpr::VK_Lanai_ABS_LO);
482303231Sdim#endif
483303231Sdim      Inst.addOperand(MCOperand::createExpr(getImm()));
484303231Sdim    } else
485303231Sdim      assert(false && "Operand type not supported.");
486303231Sdim  }
487303231Sdim
488303231Sdim  void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
489303231Sdim    assert(N == 1 && "Invalid number of operands!");
490303231Sdim    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
491303231Sdim      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
492303231Sdim    else
493303231Sdim      assert(false && "Operand type not supported.");
494303231Sdim  }
495303231Sdim
496303231Sdim  void addHiImm16Operands(MCInst &Inst, unsigned N) const {
497303231Sdim    assert(N == 1 && "Invalid number of operands!");
498303231Sdim    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
499303231Sdim      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
500303231Sdim    else if (isa<LanaiMCExpr>(getImm())) {
501303231Sdim#ifndef NDEBUG
502303231Sdim      const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
503360784Sdim      assert(SymbolRefExpr &&
504360784Sdim             SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
505303231Sdim#endif
506303231Sdim      Inst.addOperand(MCOperand::createExpr(getImm()));
507303231Sdim    } else if (isa<MCBinaryExpr>(getImm())) {
508303231Sdim#ifndef NDEBUG
509303231Sdim      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
510360784Sdim      assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
511341825Sdim             cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
512303231Sdim                 LanaiMCExpr::VK_Lanai_ABS_HI);
513303231Sdim#endif
514303231Sdim      Inst.addOperand(MCOperand::createExpr(getImm()));
515303231Sdim    } else
516303231Sdim      assert(false && "Operand type not supported.");
517303231Sdim  }
518303231Sdim
519303231Sdim  void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
520303231Sdim    assert(N == 1 && "Invalid number of operands!");
521303231Sdim    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
522303231Sdim      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
523303231Sdim    else
524303231Sdim      assert(false && "Operand type not supported.");
525303231Sdim  }
526303231Sdim
527303231Sdim  void addLoImm21Operands(MCInst &Inst, unsigned N) const {
528303231Sdim    assert(N == 1 && "Invalid number of operands!");
529303231Sdim    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
530303231Sdim      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
531303231Sdim    else if (isa<LanaiMCExpr>(getImm())) {
532303231Sdim#ifndef NDEBUG
533303231Sdim      const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
534303231Sdim      assert(SymbolRefExpr &&
535303231Sdim             SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
536303231Sdim#endif
537303231Sdim      Inst.addOperand(MCOperand::createExpr(getImm()));
538303231Sdim    } else if (isa<MCSymbolRefExpr>(getImm())) {
539303231Sdim#ifndef NDEBUG
540303231Sdim      const MCSymbolRefExpr *SymbolRefExpr =
541303231Sdim          dyn_cast<MCSymbolRefExpr>(getImm());
542303231Sdim      assert(SymbolRefExpr &&
543303231Sdim             SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
544303231Sdim#endif
545303231Sdim      Inst.addOperand(MCOperand::createExpr(getImm()));
546303231Sdim    } else if (isa<MCBinaryExpr>(getImm())) {
547303231Sdim#ifndef NDEBUG
548303231Sdim      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
549360784Sdim      assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
550360784Sdim             cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
551360784Sdim                 LanaiMCExpr::VK_Lanai_None);
552303231Sdim#endif
553303231Sdim      Inst.addOperand(MCOperand::createExpr(getImm()));
554303231Sdim    } else
555303231Sdim      assert(false && "Operand type not supported.");
556303231Sdim  }
557303231Sdim
558303231Sdim  void print(raw_ostream &OS) const override {
559303231Sdim    switch (Kind) {
560303231Sdim    case IMMEDIATE:
561303231Sdim      OS << "Imm: " << getImm() << "\n";
562303231Sdim      break;
563303231Sdim    case TOKEN:
564303231Sdim      OS << "Token: " << getToken() << "\n";
565303231Sdim      break;
566303231Sdim    case REGISTER:
567303231Sdim      OS << "Reg: %r" << getReg() << "\n";
568303231Sdim      break;
569303231Sdim    case MEMORY_IMM:
570303231Sdim      OS << "MemImm: " << *getMemOffset() << "\n";
571303231Sdim      break;
572303231Sdim    case MEMORY_REG_IMM:
573303231Sdim      OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
574303231Sdim      break;
575303231Sdim    case MEMORY_REG_REG:
576303231Sdim      assert(getMemOffset() == nullptr);
577303231Sdim      OS << "MemRegReg: " << getMemBaseReg() << "+"
578303231Sdim         << "%r" << getMemOffsetReg() << "\n";
579303231Sdim      break;
580303231Sdim    }
581303231Sdim  }
582303231Sdim
583303231Sdim  static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
584360784Sdim    auto Op = std::make_unique<LanaiOperand>(TOKEN);
585303231Sdim    Op->Tok.Data = Str.data();
586303231Sdim    Op->Tok.Length = Str.size();
587303231Sdim    Op->StartLoc = Start;
588303231Sdim    Op->EndLoc = Start;
589303231Sdim    return Op;
590303231Sdim  }
591303231Sdim
592303231Sdim  static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start,
593303231Sdim                                                 SMLoc End) {
594360784Sdim    auto Op = std::make_unique<LanaiOperand>(REGISTER);
595303231Sdim    Op->Reg.RegNum = RegNum;
596303231Sdim    Op->StartLoc = Start;
597303231Sdim    Op->EndLoc = End;
598303231Sdim    return Op;
599303231Sdim  }
600303231Sdim
601303231Sdim  static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
602303231Sdim                                                 SMLoc Start, SMLoc End) {
603360784Sdim    auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
604303231Sdim    Op->Imm.Value = Value;
605303231Sdim    Op->StartLoc = Start;
606303231Sdim    Op->EndLoc = End;
607303231Sdim    return Op;
608303231Sdim  }
609303231Sdim
610303231Sdim  static std::unique_ptr<LanaiOperand>
611303231Sdim  MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
612303231Sdim    const MCExpr *Imm = Op->getImm();
613303231Sdim    Op->Kind = MEMORY_IMM;
614303231Sdim    Op->Mem.BaseReg = 0;
615303231Sdim    Op->Mem.AluOp = LPAC::ADD;
616303231Sdim    Op->Mem.OffsetReg = 0;
617303231Sdim    Op->Mem.Offset = Imm;
618303231Sdim    return Op;
619303231Sdim  }
620303231Sdim
621303231Sdim  static std::unique_ptr<LanaiOperand>
622303231Sdim  MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
623303231Sdim                   unsigned AluOp) {
624303231Sdim    unsigned OffsetReg = Op->getReg();
625303231Sdim    Op->Kind = MEMORY_REG_REG;
626303231Sdim    Op->Mem.BaseReg = BaseReg;
627303231Sdim    Op->Mem.AluOp = AluOp;
628303231Sdim    Op->Mem.OffsetReg = OffsetReg;
629303231Sdim    Op->Mem.Offset = nullptr;
630303231Sdim    return Op;
631303231Sdim  }
632303231Sdim
633303231Sdim  static std::unique_ptr<LanaiOperand>
634303231Sdim  MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
635303231Sdim                   unsigned AluOp) {
636303231Sdim    const MCExpr *Imm = Op->getImm();
637303231Sdim    Op->Kind = MEMORY_REG_IMM;
638303231Sdim    Op->Mem.BaseReg = BaseReg;
639303231Sdim    Op->Mem.AluOp = AluOp;
640303231Sdim    Op->Mem.OffsetReg = 0;
641303231Sdim    Op->Mem.Offset = Imm;
642303231Sdim    return Op;
643303231Sdim  }
644303231Sdim};
645303231Sdim
646314564Sdim} // end anonymous namespace
647314564Sdim
648303231Sdimbool LanaiAsmParser::ParseDirective(AsmToken /*DirectiveId*/) { return true; }
649303231Sdim
650303231Sdimbool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
651303231Sdim                                             OperandVector &Operands,
652303231Sdim                                             MCStreamer &Out,
653303231Sdim                                             uint64_t &ErrorInfo,
654303231Sdim                                             bool MatchingInlineAsm) {
655303231Sdim  MCInst Inst;
656303231Sdim  SMLoc ErrorLoc;
657303231Sdim
658303231Sdim  switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
659303231Sdim  case Match_Success:
660303231Sdim    Out.EmitInstruction(Inst, SubtargetInfo);
661303231Sdim    Opcode = Inst.getOpcode();
662303231Sdim    return false;
663303231Sdim  case Match_MissingFeature:
664303231Sdim    return Error(IdLoc, "Instruction use requires option to be enabled");
665303231Sdim  case Match_MnemonicFail:
666303231Sdim    return Error(IdLoc, "Unrecognized instruction mnemonic");
667303231Sdim  case Match_InvalidOperand: {
668303231Sdim    ErrorLoc = IdLoc;
669303231Sdim    if (ErrorInfo != ~0U) {
670303231Sdim      if (ErrorInfo >= Operands.size())
671303231Sdim        return Error(IdLoc, "Too few operands for instruction");
672303231Sdim
673303231Sdim      ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
674303231Sdim      if (ErrorLoc == SMLoc())
675303231Sdim        ErrorLoc = IdLoc;
676303231Sdim    }
677303231Sdim    return Error(ErrorLoc, "Invalid operand for instruction");
678303231Sdim  }
679303231Sdim  default:
680303231Sdim    break;
681303231Sdim  }
682303231Sdim
683303231Sdim  llvm_unreachable("Unknown match type detected!");
684303231Sdim}
685303231Sdim
686303231Sdim// Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
687303231Sdim// backwards compatible with GCC and the different ways inline assembly is
688303231Sdim// handled.
689303231Sdim// TODO: see if there isn't a better way to do this.
690303231Sdimstd::unique_ptr<LanaiOperand> LanaiAsmParser::parseRegister() {
691303231Sdim  SMLoc Start = Parser.getTok().getLoc();
692303231Sdim  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
693303231Sdim
694303231Sdim  unsigned RegNum;
695303231Sdim  // Eat the '%'.
696303231Sdim  if (Lexer.getKind() == AsmToken::Percent)
697303231Sdim    Parser.Lex();
698303231Sdim  if (Lexer.getKind() == AsmToken::Identifier) {
699303231Sdim    RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
700303231Sdim    if (RegNum == 0)
701314564Sdim      return nullptr;
702303231Sdim    Parser.Lex(); // Eat identifier token
703303231Sdim    return LanaiOperand::createReg(RegNum, Start, End);
704303231Sdim  }
705314564Sdim  return nullptr;
706303231Sdim}
707303231Sdim
708303231Sdimbool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc,
709303231Sdim                                   SMLoc &EndLoc) {
710303231Sdim  const AsmToken &Tok = getParser().getTok();
711303231Sdim  StartLoc = Tok.getLoc();
712303231Sdim  EndLoc = Tok.getEndLoc();
713303231Sdim  std::unique_ptr<LanaiOperand> Op = parseRegister();
714303231Sdim  if (Op != nullptr)
715303231Sdim    RegNum = Op->getReg();
716303231Sdim  return (Op == nullptr);
717303231Sdim}
718303231Sdim
719303231Sdimstd::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
720303231Sdim  SMLoc Start = Parser.getTok().getLoc();
721303231Sdim  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
722314564Sdim  const MCExpr *Res, *RHS = nullptr;
723303231Sdim  LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;
724303231Sdim
725303231Sdim  if (Lexer.getKind() != AsmToken::Identifier)
726314564Sdim    return nullptr;
727303231Sdim
728303231Sdim  StringRef Identifier;
729303231Sdim  if (Parser.parseIdentifier(Identifier))
730314564Sdim    return nullptr;
731303231Sdim
732303231Sdim  // Check if identifier has a modifier
733303231Sdim  if (Identifier.equals_lower("hi"))
734303231Sdim    Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
735303231Sdim  else if (Identifier.equals_lower("lo"))
736303231Sdim    Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
737303231Sdim
738303231Sdim  // If the identifier corresponds to a variant then extract the real
739303231Sdim  // identifier.
740303231Sdim  if (Kind != LanaiMCExpr::VK_Lanai_None) {
741303231Sdim    if (Lexer.getKind() != AsmToken::LParen) {
742303231Sdim      Error(Lexer.getLoc(), "Expected '('");
743314564Sdim      return nullptr;
744303231Sdim    }
745303231Sdim    Lexer.Lex(); // lex '('
746303231Sdim
747303231Sdim    // Parse identifier
748303231Sdim    if (Parser.parseIdentifier(Identifier))
749314564Sdim      return nullptr;
750303231Sdim  }
751303231Sdim
752303231Sdim  // If addition parse the RHS.
753303231Sdim  if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
754314564Sdim    return nullptr;
755303231Sdim
756303231Sdim  // For variants parse the final ')'
757303231Sdim  if (Kind != LanaiMCExpr::VK_Lanai_None) {
758303231Sdim    if (Lexer.getKind() != AsmToken::RParen) {
759303231Sdim      Error(Lexer.getLoc(), "Expected ')'");
760314564Sdim      return nullptr;
761303231Sdim    }
762303231Sdim    Lexer.Lex(); // lex ')'
763303231Sdim  }
764303231Sdim
765303231Sdim  End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
766303231Sdim  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
767303231Sdim  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
768303231Sdim  Res = LanaiMCExpr::create(Kind, Expr, getContext());
769303231Sdim
770303231Sdim  // Nest if this was an addition
771303231Sdim  if (RHS)
772303231Sdim    Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
773303231Sdim
774303231Sdim  return LanaiOperand::createImm(Res, Start, End);
775303231Sdim}
776303231Sdim
777303231Sdimstd::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
778303231Sdim  SMLoc Start = Parser.getTok().getLoc();
779303231Sdim  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
780303231Sdim
781303231Sdim  const MCExpr *ExprVal;
782303231Sdim  switch (Lexer.getKind()) {
783303231Sdim  case AsmToken::Identifier:
784303231Sdim    return parseIdentifier();
785303231Sdim  case AsmToken::Plus:
786303231Sdim  case AsmToken::Minus:
787303231Sdim  case AsmToken::Integer:
788303231Sdim  case AsmToken::Dot:
789303231Sdim    if (!Parser.parseExpression(ExprVal))
790303231Sdim      return LanaiOperand::createImm(ExprVal, Start, End);
791321369Sdim    LLVM_FALLTHROUGH;
792303231Sdim  default:
793314564Sdim    return nullptr;
794303231Sdim  }
795303231Sdim}
796303231Sdim
797303231Sdimstatic unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
798303231Sdim  if (PreOp)
799303231Sdim    return LPAC::makePreOp(AluCode);
800303231Sdim  if (PostOp)
801303231Sdim    return LPAC::makePostOp(AluCode);
802303231Sdim  return AluCode;
803303231Sdim}
804303231Sdim
805303231Sdimunsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
806303231Sdim  StringRef IdString;
807303231Sdim  Parser.parseIdentifier(IdString);
808303231Sdim  unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
809303231Sdim  if (AluCode == LPAC::UNKNOWN) {
810303231Sdim    Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
811303231Sdim    return 0;
812303231Sdim  }
813303231Sdim  return AluCode;
814303231Sdim}
815303231Sdim
816303231Sdimstatic int SizeForSuffix(StringRef T) {
817303231Sdim  return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
818303231Sdim}
819303231Sdim
820303231Sdimbool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
821303231Sdim  bool PreOrPost = false;
822303231Sdim  if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
823303231Sdim    PreOrPost = true;
824303231Sdim    if (Lexer.is(AsmToken::Minus))
825303231Sdim      *OffsetValue = -SizeForSuffix(Type);
826303231Sdim    else if (Lexer.is(AsmToken::Plus))
827303231Sdim      *OffsetValue = SizeForSuffix(Type);
828303231Sdim    else
829303231Sdim      return false;
830303231Sdim
831303231Sdim    // Eat the '-' '-' or '+' '+'
832303231Sdim    Parser.Lex();
833303231Sdim    Parser.Lex();
834303231Sdim  } else if (Lexer.is(AsmToken::Star)) {
835303231Sdim    Parser.Lex(); // Eat the '*'
836303231Sdim    PreOrPost = true;
837303231Sdim  }
838303231Sdim
839303231Sdim  return PreOrPost;
840303231Sdim}
841303231Sdim
842303231Sdimbool shouldBeSls(const LanaiOperand &Op) {
843303231Sdim  // The instruction should be encoded as an SLS if the constant is word
844303231Sdim  // aligned and will fit in 21 bits
845303231Sdim  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
846303231Sdim    int64_t Value = ConstExpr->getValue();
847303231Sdim    return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
848303231Sdim  }
849303231Sdim  // The instruction should be encoded as an SLS if the operand is a symbolic
850303231Sdim  // reference with no variant.
851303231Sdim  if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
852303231Sdim    return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
853303231Sdim  // The instruction should be encoded as an SLS if the operand is a binary
854303231Sdim  // expression with the left-hand side being a symbolic reference with no
855303231Sdim  // variant.
856303231Sdim  if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
857303231Sdim    const LanaiMCExpr *LHSSymbolRefExpr =
858303231Sdim        dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
859303231Sdim    return (LHSSymbolRefExpr &&
860303231Sdim            LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
861303231Sdim  }
862303231Sdim  return false;
863303231Sdim}
864303231Sdim
865303231Sdim// Matches memory operand. Returns true if error encountered.
866314564SdimOperandMatchResultTy
867303231SdimLanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
868303231Sdim  // Try to match a memory operand.
869303231Sdim  // The memory operands are of the form:
870303231Sdim  //  (1)  Register|Immediate|'' '[' '*'? Register '*'? ']' or
871303231Sdim  //                            ^
872303231Sdim  //  (2)  '[' '*'? Register '*'? AluOperator Register ']'
873303231Sdim  //      ^
874303231Sdim  //  (3)  '[' '--'|'++' Register '--'|'++' ']'
875303231Sdim  //
876303231Sdim  //  (4) '[' Immediate ']' (for SLS)
877303231Sdim
878303231Sdim  // Store the type for use in parsing pre/post increment/decrement operators
879303231Sdim  StringRef Type;
880303231Sdim  if (Operands[0]->isToken())
881303231Sdim    Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
882303231Sdim
883303231Sdim  // Use 0 if no offset given
884303231Sdim  int OffsetValue = 0;
885303231Sdim  unsigned BaseReg = 0;
886303231Sdim  unsigned AluOp = LPAC::ADD;
887303231Sdim  bool PostOp = false, PreOp = false;
888303231Sdim
889303231Sdim  // Try to parse the offset
890303231Sdim  std::unique_ptr<LanaiOperand> Op = parseRegister();
891303231Sdim  if (!Op)
892303231Sdim    Op = parseImmediate();
893303231Sdim
894303231Sdim  // Only continue if next token is '['
895303231Sdim  if (Lexer.isNot(AsmToken::LBrac)) {
896303231Sdim    if (!Op)
897303231Sdim      return MatchOperand_NoMatch;
898303231Sdim
899303231Sdim    // The start of this custom parsing overlaps with register/immediate so
900303231Sdim    // consider this as a successful match of an operand of that type as the
901303231Sdim    // token stream can't be rewound to allow them to match separately.
902303231Sdim    Operands.push_back(std::move(Op));
903303231Sdim    return MatchOperand_Success;
904303231Sdim  }
905303231Sdim
906303231Sdim  Parser.Lex(); // Eat the '['.
907303231Sdim  std::unique_ptr<LanaiOperand> Offset = nullptr;
908303231Sdim  if (Op)
909303231Sdim    Offset.swap(Op);
910303231Sdim
911303231Sdim  // Determine if a pre operation
912303231Sdim  PreOp = parsePrePost(Type, &OffsetValue);
913303231Sdim
914303231Sdim  Op = parseRegister();
915303231Sdim  if (!Op) {
916303231Sdim    if (!Offset) {
917303231Sdim      if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
918303231Sdim        Parser.Lex(); // Eat the ']'
919303231Sdim
920303231Sdim        // Memory address operations aligned to word boundary are encoded as
921303231Sdim        // SLS, the rest as RM.
922303231Sdim        if (shouldBeSls(*Op)) {
923303231Sdim          Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
924303231Sdim        } else {
925303231Sdim          if (!Op->isLoImm16Signed()) {
926303231Sdim            Error(Parser.getTok().getLoc(),
927303231Sdim                  "Memory address is not word "
928303231Sdim                  "aligned and larger than class RM can handle");
929303231Sdim            return MatchOperand_ParseFail;
930303231Sdim          }
931303231Sdim          Operands.push_back(LanaiOperand::MorphToMemRegImm(
932303231Sdim              Lanai::R0, std::move(Op), LPAC::ADD));
933303231Sdim        }
934303231Sdim        return MatchOperand_Success;
935303231Sdim      }
936303231Sdim    }
937303231Sdim
938303231Sdim    Error(Parser.getTok().getLoc(),
939303231Sdim          "Unknown operand, expected register or immediate");
940303231Sdim    return MatchOperand_ParseFail;
941303231Sdim  }
942303231Sdim  BaseReg = Op->getReg();
943303231Sdim
944303231Sdim  // Determine if a post operation
945303231Sdim  if (!PreOp)
946303231Sdim    PostOp = parsePrePost(Type, &OffsetValue);
947303231Sdim
948303231Sdim  // If ] match form (1) else match form (2)
949303231Sdim  if (Lexer.is(AsmToken::RBrac)) {
950303231Sdim    Parser.Lex(); // Eat the ']'.
951303231Sdim    if (!Offset) {
952303231Sdim      SMLoc Start = Parser.getTok().getLoc();
953303231Sdim      SMLoc End =
954303231Sdim          SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
955303231Sdim      const MCConstantExpr *OffsetConstExpr =
956303231Sdim          MCConstantExpr::create(OffsetValue, getContext());
957303231Sdim      Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
958303231Sdim    }
959303231Sdim  } else {
960303231Sdim    if (Offset || OffsetValue != 0) {
961303231Sdim      Error(Parser.getTok().getLoc(), "Expected ']'");
962303231Sdim      return MatchOperand_ParseFail;
963303231Sdim    }
964303231Sdim
965303231Sdim    // Parse operator
966303231Sdim    AluOp = parseAluOperator(PreOp, PostOp);
967303231Sdim
968303231Sdim    // Second form requires offset register
969303231Sdim    Offset = parseRegister();
970303231Sdim    if (!BaseReg || Lexer.isNot(AsmToken::RBrac)) {
971303231Sdim      Error(Parser.getTok().getLoc(), "Expected ']'");
972303231Sdim      return MatchOperand_ParseFail;
973303231Sdim    }
974303231Sdim    Parser.Lex(); // Eat the ']'.
975303231Sdim  }
976303231Sdim
977303231Sdim  // First form has addition as operator. Add pre- or post-op indicator as
978303231Sdim  // needed.
979303231Sdim  AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
980303231Sdim
981303231Sdim  // Ensure immediate offset is not too large
982303231Sdim  if (Offset->isImm() && !Offset->isLoImm16Signed()) {
983303231Sdim    Error(Parser.getTok().getLoc(),
984303231Sdim          "Memory address is not word "
985303231Sdim          "aligned and larger than class RM can handle");
986303231Sdim    return MatchOperand_ParseFail;
987303231Sdim  }
988303231Sdim
989303231Sdim  Operands.push_back(
990303231Sdim      Offset->isImm()
991303231Sdim          ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
992303231Sdim          : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
993303231Sdim
994303231Sdim  return MatchOperand_Success;
995303231Sdim}
996303231Sdim
997303231Sdim// Looks at a token type and creates the relevant operand from this
998303231Sdim// information, adding to operands.
999303231Sdim// If operand was parsed, returns false, else true.
1000314564SdimOperandMatchResultTy
1001303231SdimLanaiAsmParser::parseOperand(OperandVector *Operands, StringRef Mnemonic) {
1002303231Sdim  // Check if the current operand has a custom associated parser, if so, try to
1003303231Sdim  // custom parse the operand, or fallback to the general approach.
1004303231Sdim  OperandMatchResultTy Result = MatchOperandParserImpl(*Operands, Mnemonic);
1005303231Sdim
1006303231Sdim  if (Result == MatchOperand_Success)
1007303231Sdim    return Result;
1008303231Sdim  if (Result == MatchOperand_ParseFail) {
1009303231Sdim    Parser.eatToEndOfStatement();
1010303231Sdim    return Result;
1011303231Sdim  }
1012303231Sdim
1013303231Sdim  // Attempt to parse token as register
1014303231Sdim  std::unique_ptr<LanaiOperand> Op = parseRegister();
1015303231Sdim
1016303231Sdim  // Attempt to parse token as immediate
1017303231Sdim  if (!Op)
1018303231Sdim    Op = parseImmediate();
1019303231Sdim
1020303231Sdim  // If the token could not be parsed then fail
1021303231Sdim  if (!Op) {
1022303231Sdim    Error(Parser.getTok().getLoc(), "Unknown operand");
1023303231Sdim    Parser.eatToEndOfStatement();
1024303231Sdim    return MatchOperand_ParseFail;
1025303231Sdim  }
1026303231Sdim
1027303231Sdim  // Push back parsed operand into list of operands
1028303231Sdim  Operands->push_back(std::move(Op));
1029303231Sdim
1030303231Sdim  return MatchOperand_Success;
1031303231Sdim}
1032303231Sdim
1033303231Sdim// Split the mnemonic into ASM operand, conditional code and instruction
1034303231Sdim// qualifier (half-word, byte).
1035303231SdimStringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1036303231Sdim                                        OperandVector *Operands) {
1037303231Sdim  size_t Next = Name.find('.');
1038303231Sdim
1039303231Sdim  StringRef Mnemonic = Name;
1040303231Sdim
1041303231Sdim  bool IsBRR = false;
1042303231Sdim  if (Name.endswith(".r")) {
1043303231Sdim    Mnemonic = Name.substr(0, Name.size() - 2);
1044303231Sdim    IsBRR = true;
1045303231Sdim  }
1046303231Sdim
1047303231Sdim  // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1048303231Sdim  if (Mnemonic[0] == 'b' ||
1049303231Sdim      (Mnemonic[0] == 's' && !Mnemonic.startswith("sel") &&
1050303231Sdim       !Mnemonic.startswith("st"))) {
1051303231Sdim    // Parse instructions with a conditional code. For example, 'bne' is
1052303231Sdim    // converted into two operands 'b' and 'ne'.
1053303231Sdim    LPCC::CondCode CondCode =
1054303231Sdim        LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1055303231Sdim    if (CondCode != LPCC::UNKNOWN) {
1056303231Sdim      Mnemonic = Mnemonic.slice(0, 1);
1057303231Sdim      Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1058303231Sdim      Operands->push_back(LanaiOperand::createImm(
1059303231Sdim          MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1060303231Sdim      if (IsBRR) {
1061303231Sdim        Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1062303231Sdim      }
1063303231Sdim      return Mnemonic;
1064303231Sdim    }
1065303231Sdim  }
1066303231Sdim
1067303231Sdim  // Parse other instructions with condition codes (RR instructions).
1068303231Sdim  // We ignore .f here and assume they are flag-setting operations, not
1069303231Sdim  // conditional codes (except for select instructions where flag-setting
1070303231Sdim  // variants are not yet implemented).
1071303231Sdim  if (Mnemonic.startswith("sel") ||
1072303231Sdim      (!Mnemonic.endswith(".f") && !Mnemonic.startswith("st"))) {
1073303231Sdim    LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
1074303231Sdim    if (CondCode != LPCC::UNKNOWN) {
1075303231Sdim      size_t Next = Mnemonic.rfind('.', Name.size());
1076303231Sdim      // 'sel' doesn't use a predicate operand whose printer adds the period,
1077303231Sdim      // but instead has the period as part of the identifier (i.e., 'sel.' is
1078303231Sdim      // expected by the generated matcher). If the mnemonic starts with 'sel'
1079303231Sdim      // then include the period as part of the mnemonic, else don't include it
1080303231Sdim      // as part of the mnemonic.
1081303231Sdim      if (Mnemonic.startswith("sel")) {
1082303231Sdim        Mnemonic = Mnemonic.substr(0, Next + 1);
1083303231Sdim      } else {
1084303231Sdim        Mnemonic = Mnemonic.substr(0, Next);
1085303231Sdim      }
1086303231Sdim      Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1087303231Sdim      Operands->push_back(LanaiOperand::createImm(
1088303231Sdim          MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1089303231Sdim      return Mnemonic;
1090303231Sdim    }
1091303231Sdim  }
1092303231Sdim
1093303231Sdim  Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1094303231Sdim  if (IsBRR) {
1095303231Sdim    Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1096303231Sdim  }
1097303231Sdim
1098303231Sdim  return Mnemonic;
1099303231Sdim}
1100303231Sdim
1101321369Sdimstatic bool IsMemoryAssignmentError(const OperandVector &Operands) {
1102303231Sdim  // Detects if a memory operation has an erroneous base register modification.
1103303231Sdim  // Memory operations are detected by matching the types of operands.
1104303231Sdim  //
1105303231Sdim  // TODO: This test is focussed on one specific instance (ld/st).
1106303231Sdim  // Extend it to handle more cases or be more robust.
1107303231Sdim  bool Modifies = false;
1108303231Sdim
1109303231Sdim  int Offset = 0;
1110303231Sdim
1111303231Sdim  if (Operands.size() < 5)
1112303231Sdim    return false;
1113303231Sdim  else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1114303231Sdim           Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1115303231Sdim    Offset = 0;
1116303231Sdim  else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1117303231Sdim           Operands[2]->isReg() && Operands[3]->isImm() &&
1118303231Sdim           Operands[4]->isImm() && Operands[5]->isReg())
1119303231Sdim    Offset = 1;
1120303231Sdim  else
1121303231Sdim    return false;
1122303231Sdim
1123303231Sdim  int PossibleAluOpIdx = Offset + 3;
1124303231Sdim  int PossibleBaseIdx = Offset + 1;
1125303231Sdim  int PossibleDestIdx = Offset + 4;
1126303231Sdim  if (LanaiOperand *PossibleAluOp =
1127303231Sdim          static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1128303231Sdim    if (PossibleAluOp->isImm())
1129303231Sdim      if (const MCConstantExpr *ConstExpr =
1130303231Sdim              dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1131303231Sdim        Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1132303231Sdim  return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1133303231Sdim         Operands[PossibleDestIdx]->isReg() &&
1134303231Sdim         Operands[PossibleBaseIdx]->getReg() ==
1135303231Sdim             Operands[PossibleDestIdx]->getReg();
1136303231Sdim}
1137303231Sdim
1138303231Sdimstatic bool IsRegister(const MCParsedAsmOperand &op) {
1139303231Sdim  return static_cast<const LanaiOperand &>(op).isReg();
1140303231Sdim}
1141303231Sdim
1142303231Sdimstatic bool MaybePredicatedInst(const OperandVector &Operands) {
1143303231Sdim  if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1144303231Sdim      !IsRegister(*Operands[2]))
1145303231Sdim    return false;
1146303231Sdim  return StringSwitch<bool>(
1147303231Sdim             static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1148303231Sdim      .StartsWith("addc", true)
1149303231Sdim      .StartsWith("add", true)
1150303231Sdim      .StartsWith("and", true)
1151303231Sdim      .StartsWith("sh", true)
1152303231Sdim      .StartsWith("subb", true)
1153303231Sdim      .StartsWith("sub", true)
1154303231Sdim      .StartsWith("or", true)
1155303231Sdim      .StartsWith("xor", true)
1156303231Sdim      .Default(false);
1157303231Sdim}
1158303231Sdim
1159303231Sdimbool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/,
1160303231Sdim                                      StringRef Name, SMLoc NameLoc,
1161303231Sdim                                      OperandVector &Operands) {
1162303231Sdim  // First operand is token for instruction
1163303231Sdim  StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1164303231Sdim
1165303231Sdim  // If there are no more operands, then finish
1166303231Sdim  if (Lexer.is(AsmToken::EndOfStatement))
1167303231Sdim    return false;
1168303231Sdim
1169303231Sdim  // Parse first operand
1170303231Sdim  if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1171303231Sdim    return true;
1172303231Sdim
1173303231Sdim  // If it is a st instruction with one 1 operand then it is a "store true".
1174303231Sdim  // Transform <"st"> to <"s">, <LPCC:ICC_T>
1175303231Sdim  if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1176303231Sdim      Operands.size() == 2) {
1177303231Sdim    Operands.erase(Operands.begin(), Operands.begin() + 1);
1178303231Sdim    Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1179303231Sdim    Operands.insert(Operands.begin() + 1,
1180303231Sdim                    LanaiOperand::createImm(
1181303231Sdim                        MCConstantExpr::create(LPCC::ICC_T, getContext()),
1182303231Sdim                        NameLoc, NameLoc));
1183303231Sdim  }
1184303231Sdim
1185303231Sdim  // If the instruction is a bt instruction with 1 operand (in assembly) then it
1186303231Sdim  // is an unconditional branch instruction and the first two elements of
1187303231Sdim  // operands need to be merged.
1188303231Sdim  if (Lexer.is(AsmToken::EndOfStatement) && Name.startswith("bt") &&
1189303231Sdim      Operands.size() == 3) {
1190303231Sdim    Operands.erase(Operands.begin(), Operands.begin() + 2);
1191303231Sdim    Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1192303231Sdim  }
1193303231Sdim
1194303231Sdim  // Parse until end of statement, consuming commas between operands
1195303231Sdim  while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1196303231Sdim    // Consume comma token
1197303231Sdim    Lex();
1198303231Sdim
1199303231Sdim    // Parse next operand
1200303231Sdim    if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1201303231Sdim      return true;
1202303231Sdim  }
1203303231Sdim
1204303231Sdim  if (IsMemoryAssignmentError(Operands)) {
1205303231Sdim    Error(Parser.getTok().getLoc(),
1206303231Sdim          "the destination register can't equal the base register in an "
1207303231Sdim          "instruction that modifies the base register.");
1208303231Sdim    return true;
1209303231Sdim  }
1210303231Sdim
1211303231Sdim  // Insert always true operand for instruction that may be predicated but
1212303231Sdim  // are not. Currently the autogenerated parser always expects a predicate.
1213303231Sdim  if (MaybePredicatedInst(Operands)) {
1214303231Sdim    Operands.insert(Operands.begin() + 1,
1215303231Sdim                    LanaiOperand::createImm(
1216303231Sdim                        MCConstantExpr::create(LPCC::ICC_T, getContext()),
1217303231Sdim                        NameLoc, NameLoc));
1218303231Sdim  }
1219303231Sdim
1220303231Sdim  return false;
1221303231Sdim}
1222303231Sdim
1223303231Sdim#define GET_REGISTER_MATCHER
1224303231Sdim#define GET_MATCHER_IMPLEMENTATION
1225303231Sdim#include "LanaiGenAsmMatcher.inc"
1226303231Sdim
1227360784Sdimextern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmParser() {
1228314564Sdim  RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget());
1229303231Sdim}
1230