xref: /aosp_15_r20/external/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- LanaiAsmParser.cpp - Parse Lanai assembly to MCInst instructions --===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "Lanai.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/LanaiMCExpr.h"
12*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/LanaiMCTargetDesc.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmLexer.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCTargetAsmParser.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker namespace llvm {
27*9880d681SAndroid Build Coastguard Worker namespace {
28*9880d681SAndroid Build Coastguard Worker struct LanaiOperand;
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker class LanaiAsmParser : public MCTargetAsmParser {
31*9880d681SAndroid Build Coastguard Worker   // Parse operands
32*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<LanaiOperand> parseRegister();
33*9880d681SAndroid Build Coastguard Worker 
34*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<LanaiOperand> parseImmediate();
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<LanaiOperand> parseIdentifier();
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker   unsigned parseAluOperator(bool PreOp, bool PostOp);
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker   // Split the mnemonic stripping conditional code and quantifiers
41*9880d681SAndroid Build Coastguard Worker   StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
42*9880d681SAndroid Build Coastguard Worker                           OperandVector *Operands);
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker   bool parsePrePost(StringRef Type, int *OffsetValue);
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker   bool ParseDirective(AsmToken DirectiveID) override;
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
49*9880d681SAndroid Build Coastguard Worker                         SMLoc NameLoc, OperandVector &Operands) override;
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker   bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override;
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker   bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
54*9880d681SAndroid Build Coastguard Worker                                OperandVector &Operands, MCStreamer &Out,
55*9880d681SAndroid Build Coastguard Worker                                uint64_t &ErrorInfo,
56*9880d681SAndroid Build Coastguard Worker                                bool MatchingInlineAsm) override;
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker // Auto-generated instruction matching functions
59*9880d681SAndroid Build Coastguard Worker #define GET_ASSEMBLER_HEADER
60*9880d681SAndroid Build Coastguard Worker #include "LanaiGenAsmMatcher.inc"
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseOperand(OperandVector *Operands,
63*9880d681SAndroid Build Coastguard Worker                                     StringRef Mnemonic);
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseMemoryOperand(OperandVector &Operands);
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker public:
LanaiAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)68*9880d681SAndroid Build Coastguard Worker   LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
69*9880d681SAndroid Build Coastguard Worker                  const MCInstrInfo &MII, const MCTargetOptions &Options)
70*9880d681SAndroid Build Coastguard Worker       : MCTargetAsmParser(Options, STI), Parser(Parser),
71*9880d681SAndroid Build Coastguard Worker         Lexer(Parser.getLexer()), SubtargetInfo(STI) {
72*9880d681SAndroid Build Coastguard Worker     setAvailableFeatures(
73*9880d681SAndroid Build Coastguard Worker         ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
74*9880d681SAndroid Build Coastguard Worker   }
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker private:
77*9880d681SAndroid Build Coastguard Worker   MCAsmParser &Parser;
78*9880d681SAndroid Build Coastguard Worker   MCAsmLexer &Lexer;
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker   const MCSubtargetInfo &SubtargetInfo;
81*9880d681SAndroid Build Coastguard Worker };
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker // Auto-generated by TableGen
84*9880d681SAndroid Build Coastguard Worker static unsigned MatchRegisterName(llvm::StringRef Name);
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker // LanaiOperand - Instances of this class represented a parsed machine
87*9880d681SAndroid Build Coastguard Worker // instruction
88*9880d681SAndroid Build Coastguard Worker struct LanaiOperand : public MCParsedAsmOperand {
89*9880d681SAndroid Build Coastguard Worker   enum KindTy {
90*9880d681SAndroid Build Coastguard Worker     TOKEN,
91*9880d681SAndroid Build Coastguard Worker     REGISTER,
92*9880d681SAndroid Build Coastguard Worker     IMMEDIATE,
93*9880d681SAndroid Build Coastguard Worker     MEMORY_IMM,
94*9880d681SAndroid Build Coastguard Worker     MEMORY_REG_IMM,
95*9880d681SAndroid Build Coastguard Worker     MEMORY_REG_REG,
96*9880d681SAndroid Build Coastguard Worker   } Kind;
97*9880d681SAndroid Build Coastguard Worker 
98*9880d681SAndroid Build Coastguard Worker   SMLoc StartLoc, EndLoc;
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker   struct Token {
101*9880d681SAndroid Build Coastguard Worker     const char *Data;
102*9880d681SAndroid Build Coastguard Worker     unsigned Length;
103*9880d681SAndroid Build Coastguard Worker   };
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker   struct RegOp {
106*9880d681SAndroid Build Coastguard Worker     unsigned RegNum;
107*9880d681SAndroid Build Coastguard Worker   };
108*9880d681SAndroid Build Coastguard Worker 
109*9880d681SAndroid Build Coastguard Worker   struct ImmOp {
110*9880d681SAndroid Build Coastguard Worker     const MCExpr *Value;
111*9880d681SAndroid Build Coastguard Worker   };
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker   struct MemOp {
114*9880d681SAndroid Build Coastguard Worker     unsigned BaseReg;
115*9880d681SAndroid Build Coastguard Worker     unsigned OffsetReg;
116*9880d681SAndroid Build Coastguard Worker     unsigned AluOp;
117*9880d681SAndroid Build Coastguard Worker     const MCExpr *Offset;
118*9880d681SAndroid Build Coastguard Worker   };
119*9880d681SAndroid Build Coastguard Worker 
120*9880d681SAndroid Build Coastguard Worker   union {
121*9880d681SAndroid Build Coastguard Worker     struct Token Tok;
122*9880d681SAndroid Build Coastguard Worker     struct RegOp Reg;
123*9880d681SAndroid Build Coastguard Worker     struct ImmOp Imm;
124*9880d681SAndroid Build Coastguard Worker     struct MemOp Mem;
125*9880d681SAndroid Build Coastguard Worker   };
126*9880d681SAndroid Build Coastguard Worker 
LanaiOperandllvm::__anonc64afc020111::LanaiOperand127*9880d681SAndroid Build Coastguard Worker   explicit LanaiOperand(KindTy Kind) : MCParsedAsmOperand(), Kind(Kind) {}
128*9880d681SAndroid Build Coastguard Worker 
129*9880d681SAndroid Build Coastguard Worker public:
130*9880d681SAndroid Build Coastguard Worker   // The functions below are used by the autogenerated ASM matcher and hence to
131*9880d681SAndroid Build Coastguard Worker   // be of the form expected.
132*9880d681SAndroid Build Coastguard Worker 
133*9880d681SAndroid Build Coastguard Worker   // getStartLoc - Gets location of the first token of this operand
getStartLocllvm::__anonc64afc020111::LanaiOperand134*9880d681SAndroid Build Coastguard Worker   SMLoc getStartLoc() const override { return StartLoc; }
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker   // getEndLoc - Gets location of the last token of this operand
getEndLocllvm::__anonc64afc020111::LanaiOperand137*9880d681SAndroid Build Coastguard Worker   SMLoc getEndLoc() const override { return EndLoc; }
138*9880d681SAndroid Build Coastguard Worker 
getRegllvm::__anonc64afc020111::LanaiOperand139*9880d681SAndroid Build Coastguard Worker   unsigned getReg() const override {
140*9880d681SAndroid Build Coastguard Worker     assert(isReg() && "Invalid type access!");
141*9880d681SAndroid Build Coastguard Worker     return Reg.RegNum;
142*9880d681SAndroid Build Coastguard Worker   }
143*9880d681SAndroid Build Coastguard Worker 
getImmllvm::__anonc64afc020111::LanaiOperand144*9880d681SAndroid Build Coastguard Worker   const MCExpr *getImm() const {
145*9880d681SAndroid Build Coastguard Worker     assert(isImm() && "Invalid type access!");
146*9880d681SAndroid Build Coastguard Worker     return Imm.Value;
147*9880d681SAndroid Build Coastguard Worker   }
148*9880d681SAndroid Build Coastguard Worker 
getTokenllvm::__anonc64afc020111::LanaiOperand149*9880d681SAndroid Build Coastguard Worker   StringRef getToken() const {
150*9880d681SAndroid Build Coastguard Worker     assert(isToken() && "Invalid type access!");
151*9880d681SAndroid Build Coastguard Worker     return StringRef(Tok.Data, Tok.Length);
152*9880d681SAndroid Build Coastguard Worker   }
153*9880d681SAndroid Build Coastguard Worker 
getMemBaseRegllvm::__anonc64afc020111::LanaiOperand154*9880d681SAndroid Build Coastguard Worker   unsigned getMemBaseReg() const {
155*9880d681SAndroid Build Coastguard Worker     assert(isMem() && "Invalid type access!");
156*9880d681SAndroid Build Coastguard Worker     return Mem.BaseReg;
157*9880d681SAndroid Build Coastguard Worker   }
158*9880d681SAndroid Build Coastguard Worker 
getMemOffsetRegllvm::__anonc64afc020111::LanaiOperand159*9880d681SAndroid Build Coastguard Worker   unsigned getMemOffsetReg() const {
160*9880d681SAndroid Build Coastguard Worker     assert(isMem() && "Invalid type access!");
161*9880d681SAndroid Build Coastguard Worker     return Mem.OffsetReg;
162*9880d681SAndroid Build Coastguard Worker   }
163*9880d681SAndroid Build Coastguard Worker 
getMemOffsetllvm::__anonc64afc020111::LanaiOperand164*9880d681SAndroid Build Coastguard Worker   const MCExpr *getMemOffset() const {
165*9880d681SAndroid Build Coastguard Worker     assert(isMem() && "Invalid type access!");
166*9880d681SAndroid Build Coastguard Worker     return Mem.Offset;
167*9880d681SAndroid Build Coastguard Worker   }
168*9880d681SAndroid Build Coastguard Worker 
getMemOpllvm::__anonc64afc020111::LanaiOperand169*9880d681SAndroid Build Coastguard Worker   unsigned getMemOp() const {
170*9880d681SAndroid Build Coastguard Worker     assert(isMem() && "Invalid type access!");
171*9880d681SAndroid Build Coastguard Worker     return Mem.AluOp;
172*9880d681SAndroid Build Coastguard Worker   }
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker   // Functions for testing operand type
isRegllvm::__anonc64afc020111::LanaiOperand175*9880d681SAndroid Build Coastguard Worker   bool isReg() const override { return Kind == REGISTER; }
176*9880d681SAndroid Build Coastguard Worker 
isImmllvm::__anonc64afc020111::LanaiOperand177*9880d681SAndroid Build Coastguard Worker   bool isImm() const override { return Kind == IMMEDIATE; }
178*9880d681SAndroid Build Coastguard Worker 
isMemllvm::__anonc64afc020111::LanaiOperand179*9880d681SAndroid Build Coastguard Worker   bool isMem() const override {
180*9880d681SAndroid Build Coastguard Worker     return isMemImm() || isMemRegImm() || isMemRegReg();
181*9880d681SAndroid Build Coastguard Worker   }
182*9880d681SAndroid Build Coastguard Worker 
isMemImmllvm::__anonc64afc020111::LanaiOperand183*9880d681SAndroid Build Coastguard Worker   bool isMemImm() const { return Kind == MEMORY_IMM; }
184*9880d681SAndroid Build Coastguard Worker 
isMemRegImmllvm::__anonc64afc020111::LanaiOperand185*9880d681SAndroid Build Coastguard Worker   bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
186*9880d681SAndroid Build Coastguard Worker 
isMemRegRegllvm::__anonc64afc020111::LanaiOperand187*9880d681SAndroid Build Coastguard Worker   bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
188*9880d681SAndroid Build Coastguard Worker 
isMemSplsllvm::__anonc64afc020111::LanaiOperand189*9880d681SAndroid Build Coastguard Worker   bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
190*9880d681SAndroid Build Coastguard Worker 
isTokenllvm::__anonc64afc020111::LanaiOperand191*9880d681SAndroid Build Coastguard Worker   bool isToken() const override { return Kind == TOKEN; }
192*9880d681SAndroid Build Coastguard Worker 
isBrImmllvm::__anonc64afc020111::LanaiOperand193*9880d681SAndroid Build Coastguard Worker   bool isBrImm() {
194*9880d681SAndroid Build Coastguard Worker     if (!isImm())
195*9880d681SAndroid Build Coastguard Worker       return false;
196*9880d681SAndroid Build Coastguard Worker 
197*9880d681SAndroid Build Coastguard Worker     // Constant case
198*9880d681SAndroid Build Coastguard Worker     const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value);
199*9880d681SAndroid Build Coastguard Worker     if (!MCE)
200*9880d681SAndroid Build Coastguard Worker       return true;
201*9880d681SAndroid Build Coastguard Worker     int64_t Value = MCE->getValue();
202*9880d681SAndroid Build Coastguard Worker     // Check if value fits in 25 bits with 2 least significant bits 0.
203*9880d681SAndroid Build Coastguard Worker     return isShiftedUInt<23, 2>(static_cast<int32_t>(Value));
204*9880d681SAndroid Build Coastguard Worker   }
205*9880d681SAndroid Build Coastguard Worker 
isBrTargetllvm::__anonc64afc020111::LanaiOperand206*9880d681SAndroid Build Coastguard Worker   bool isBrTarget() { return isBrImm() || isToken(); }
207*9880d681SAndroid Build Coastguard Worker 
isCallTargetllvm::__anonc64afc020111::LanaiOperand208*9880d681SAndroid Build Coastguard Worker   bool isCallTarget() { return isImm() || isToken(); }
209*9880d681SAndroid Build Coastguard Worker 
isHiImm16llvm::__anonc64afc020111::LanaiOperand210*9880d681SAndroid Build Coastguard Worker   bool isHiImm16() {
211*9880d681SAndroid Build Coastguard Worker     if (!isImm())
212*9880d681SAndroid Build Coastguard Worker       return false;
213*9880d681SAndroid Build Coastguard Worker 
214*9880d681SAndroid Build Coastguard Worker     // Constant case
215*9880d681SAndroid Build Coastguard Worker     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
216*9880d681SAndroid Build Coastguard Worker       int64_t Value = ConstExpr->getValue();
217*9880d681SAndroid Build Coastguard Worker       return Value != 0 && isShiftedUInt<16, 16>(Value);
218*9880d681SAndroid Build Coastguard Worker     }
219*9880d681SAndroid Build Coastguard Worker 
220*9880d681SAndroid Build Coastguard Worker     // Symbolic reference expression
221*9880d681SAndroid Build Coastguard Worker     if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
222*9880d681SAndroid Build Coastguard Worker       return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
223*9880d681SAndroid Build Coastguard Worker 
224*9880d681SAndroid Build Coastguard Worker     // Binary expression
225*9880d681SAndroid Build Coastguard Worker     if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
226*9880d681SAndroid Build Coastguard Worker       if (const LanaiMCExpr *SymbolRefExpr =
227*9880d681SAndroid Build Coastguard Worker               dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
228*9880d681SAndroid Build Coastguard Worker         return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker     return false;
231*9880d681SAndroid Build Coastguard Worker   }
232*9880d681SAndroid Build Coastguard Worker 
isHiImm16Andllvm::__anonc64afc020111::LanaiOperand233*9880d681SAndroid Build Coastguard Worker   bool isHiImm16And() {
234*9880d681SAndroid Build Coastguard Worker     if (!isImm())
235*9880d681SAndroid Build Coastguard Worker       return false;
236*9880d681SAndroid Build Coastguard Worker 
237*9880d681SAndroid Build Coastguard Worker     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
238*9880d681SAndroid Build Coastguard Worker     if (ConstExpr) {
239*9880d681SAndroid Build Coastguard Worker       int64_t Value = ConstExpr->getValue();
240*9880d681SAndroid Build Coastguard Worker       // Check if in the form 0xXYZWffff
241*9880d681SAndroid Build Coastguard Worker       return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);
242*9880d681SAndroid Build Coastguard Worker     }
243*9880d681SAndroid Build Coastguard Worker     return false;
244*9880d681SAndroid Build Coastguard Worker   }
245*9880d681SAndroid Build Coastguard Worker 
isLoImm16llvm::__anonc64afc020111::LanaiOperand246*9880d681SAndroid Build Coastguard Worker   bool isLoImm16() {
247*9880d681SAndroid Build Coastguard Worker     if (!isImm())
248*9880d681SAndroid Build Coastguard Worker       return false;
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker     // Constant case
251*9880d681SAndroid Build Coastguard Worker     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
252*9880d681SAndroid Build Coastguard Worker       int64_t Value = ConstExpr->getValue();
253*9880d681SAndroid Build Coastguard Worker       // Check if value fits in 16 bits
254*9880d681SAndroid Build Coastguard Worker       return isUInt<16>(static_cast<int32_t>(Value));
255*9880d681SAndroid Build Coastguard Worker     }
256*9880d681SAndroid Build Coastguard Worker 
257*9880d681SAndroid Build Coastguard Worker     // Symbolic reference expression
258*9880d681SAndroid Build Coastguard Worker     if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
259*9880d681SAndroid Build Coastguard Worker       return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
260*9880d681SAndroid Build Coastguard Worker 
261*9880d681SAndroid Build Coastguard Worker     // Binary expression
262*9880d681SAndroid Build Coastguard Worker     if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
263*9880d681SAndroid Build Coastguard Worker       if (const LanaiMCExpr *SymbolRefExpr =
264*9880d681SAndroid Build Coastguard Worker               dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
265*9880d681SAndroid Build Coastguard Worker         return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
266*9880d681SAndroid Build Coastguard Worker 
267*9880d681SAndroid Build Coastguard Worker     return false;
268*9880d681SAndroid Build Coastguard Worker   }
269*9880d681SAndroid Build Coastguard Worker 
isLoImm16Signedllvm::__anonc64afc020111::LanaiOperand270*9880d681SAndroid Build Coastguard Worker   bool isLoImm16Signed() {
271*9880d681SAndroid Build Coastguard Worker     if (!isImm())
272*9880d681SAndroid Build Coastguard Worker       return false;
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker     // Constant case
275*9880d681SAndroid Build Coastguard Worker     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
276*9880d681SAndroid Build Coastguard Worker       int64_t Value = ConstExpr->getValue();
277*9880d681SAndroid Build Coastguard Worker       // Check if value fits in 16 bits or value of the form 0xffffxyzw
278*9880d681SAndroid Build Coastguard Worker       return isInt<16>(static_cast<int32_t>(Value));
279*9880d681SAndroid Build Coastguard Worker     }
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker     // Symbolic reference expression
282*9880d681SAndroid Build Coastguard Worker     if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
283*9880d681SAndroid Build Coastguard Worker       return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker     // Binary expression
286*9880d681SAndroid Build Coastguard Worker     if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
287*9880d681SAndroid Build Coastguard Worker       if (const LanaiMCExpr *SymbolRefExpr =
288*9880d681SAndroid Build Coastguard Worker               dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
289*9880d681SAndroid Build Coastguard Worker         return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
290*9880d681SAndroid Build Coastguard Worker 
291*9880d681SAndroid Build Coastguard Worker     return false;
292*9880d681SAndroid Build Coastguard Worker   }
293*9880d681SAndroid Build Coastguard Worker 
isLoImm16Andllvm::__anonc64afc020111::LanaiOperand294*9880d681SAndroid Build Coastguard Worker   bool isLoImm16And() {
295*9880d681SAndroid Build Coastguard Worker     if (!isImm())
296*9880d681SAndroid Build Coastguard Worker       return false;
297*9880d681SAndroid Build Coastguard Worker 
298*9880d681SAndroid Build Coastguard Worker     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
299*9880d681SAndroid Build Coastguard Worker     if (ConstExpr) {
300*9880d681SAndroid Build Coastguard Worker       int64_t Value = ConstExpr->getValue();
301*9880d681SAndroid Build Coastguard Worker       // Check if in the form 0xffffXYZW
302*9880d681SAndroid Build Coastguard Worker       return ((Value & ~0xffff) == 0xffff0000);
303*9880d681SAndroid Build Coastguard Worker     }
304*9880d681SAndroid Build Coastguard Worker     return false;
305*9880d681SAndroid Build Coastguard Worker   }
306*9880d681SAndroid Build Coastguard Worker 
isImmShiftllvm::__anonc64afc020111::LanaiOperand307*9880d681SAndroid Build Coastguard Worker   bool isImmShift() {
308*9880d681SAndroid Build Coastguard Worker     if (!isImm())
309*9880d681SAndroid Build Coastguard Worker       return false;
310*9880d681SAndroid Build Coastguard Worker 
311*9880d681SAndroid Build Coastguard Worker     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
312*9880d681SAndroid Build Coastguard Worker     if (!ConstExpr)
313*9880d681SAndroid Build Coastguard Worker       return false;
314*9880d681SAndroid Build Coastguard Worker     int64_t Value = ConstExpr->getValue();
315*9880d681SAndroid Build Coastguard Worker     return (Value >= -31) && (Value <= 31);
316*9880d681SAndroid Build Coastguard Worker   }
317*9880d681SAndroid Build Coastguard Worker 
isLoImm21llvm::__anonc64afc020111::LanaiOperand318*9880d681SAndroid Build Coastguard Worker   bool isLoImm21() {
319*9880d681SAndroid Build Coastguard Worker     if (!isImm())
320*9880d681SAndroid Build Coastguard Worker       return false;
321*9880d681SAndroid Build Coastguard Worker 
322*9880d681SAndroid Build Coastguard Worker     // Constant case
323*9880d681SAndroid Build Coastguard Worker     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
324*9880d681SAndroid Build Coastguard Worker       int64_t Value = ConstExpr->getValue();
325*9880d681SAndroid Build Coastguard Worker       return isUInt<21>(Value);
326*9880d681SAndroid Build Coastguard Worker     }
327*9880d681SAndroid Build Coastguard Worker 
328*9880d681SAndroid Build Coastguard Worker     // Symbolic reference expression
329*9880d681SAndroid Build Coastguard Worker     if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
330*9880d681SAndroid Build Coastguard Worker       return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
331*9880d681SAndroid Build Coastguard Worker     if (const MCSymbolRefExpr *SymbolRefExpr =
332*9880d681SAndroid Build Coastguard Worker             dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
333*9880d681SAndroid Build Coastguard Worker       return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
334*9880d681SAndroid Build Coastguard Worker     }
335*9880d681SAndroid Build Coastguard Worker 
336*9880d681SAndroid Build Coastguard Worker     // Binary expression
337*9880d681SAndroid Build Coastguard Worker     if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
338*9880d681SAndroid Build Coastguard Worker       if (const LanaiMCExpr *SymbolRefExpr =
339*9880d681SAndroid Build Coastguard Worker               dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
340*9880d681SAndroid Build Coastguard Worker         return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
341*9880d681SAndroid Build Coastguard Worker       if (const MCSymbolRefExpr *SymbolRefExpr =
342*9880d681SAndroid Build Coastguard Worker               dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
343*9880d681SAndroid Build Coastguard Worker         return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
344*9880d681SAndroid Build Coastguard Worker     }
345*9880d681SAndroid Build Coastguard Worker 
346*9880d681SAndroid Build Coastguard Worker     return false;
347*9880d681SAndroid Build Coastguard Worker   }
348*9880d681SAndroid Build Coastguard Worker 
isImm10llvm::__anonc64afc020111::LanaiOperand349*9880d681SAndroid Build Coastguard Worker   bool isImm10() {
350*9880d681SAndroid Build Coastguard Worker     if (!isImm())
351*9880d681SAndroid Build Coastguard Worker       return false;
352*9880d681SAndroid Build Coastguard Worker 
353*9880d681SAndroid Build Coastguard Worker     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
354*9880d681SAndroid Build Coastguard Worker     if (!ConstExpr)
355*9880d681SAndroid Build Coastguard Worker       return false;
356*9880d681SAndroid Build Coastguard Worker     int64_t Value = ConstExpr->getValue();
357*9880d681SAndroid Build Coastguard Worker     return isInt<10>(Value);
358*9880d681SAndroid Build Coastguard Worker   }
359*9880d681SAndroid Build Coastguard Worker 
isCondCodellvm::__anonc64afc020111::LanaiOperand360*9880d681SAndroid Build Coastguard Worker   bool isCondCode() {
361*9880d681SAndroid Build Coastguard Worker     if (!isImm())
362*9880d681SAndroid Build Coastguard Worker       return false;
363*9880d681SAndroid Build Coastguard Worker 
364*9880d681SAndroid Build Coastguard Worker     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
365*9880d681SAndroid Build Coastguard Worker     if (!ConstExpr)
366*9880d681SAndroid Build Coastguard Worker       return false;
367*9880d681SAndroid Build Coastguard Worker     uint64_t Value = ConstExpr->getValue();
368*9880d681SAndroid Build Coastguard Worker     // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the
369*9880d681SAndroid Build Coastguard Worker     // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then
370*9880d681SAndroid Build Coastguard Worker     // value corresponds to a valid condition code.
371*9880d681SAndroid Build Coastguard Worker     return Value < LPCC::UNKNOWN;
372*9880d681SAndroid Build Coastguard Worker   }
373*9880d681SAndroid Build Coastguard Worker 
addExprllvm::__anonc64afc020111::LanaiOperand374*9880d681SAndroid Build Coastguard Worker   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
375*9880d681SAndroid Build Coastguard Worker     // Add as immediates where possible. Null MCExpr = 0
376*9880d681SAndroid Build Coastguard Worker     if (Expr == nullptr)
377*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(0));
378*9880d681SAndroid Build Coastguard Worker     else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
379*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(
380*9880d681SAndroid Build Coastguard Worker           MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
381*9880d681SAndroid Build Coastguard Worker     else
382*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(Expr));
383*9880d681SAndroid Build Coastguard Worker   }
384*9880d681SAndroid Build Coastguard Worker 
addRegOperandsllvm::__anonc64afc020111::LanaiOperand385*9880d681SAndroid Build Coastguard Worker   void addRegOperands(MCInst &Inst, unsigned N) const {
386*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
387*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(getReg()));
388*9880d681SAndroid Build Coastguard Worker   }
389*9880d681SAndroid Build Coastguard Worker 
addImmOperandsllvm::__anonc64afc020111::LanaiOperand390*9880d681SAndroid Build Coastguard Worker   void addImmOperands(MCInst &Inst, unsigned N) const {
391*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
392*9880d681SAndroid Build Coastguard Worker     addExpr(Inst, getImm());
393*9880d681SAndroid Build Coastguard Worker   }
394*9880d681SAndroid Build Coastguard Worker 
addBrTargetOperandsllvm::__anonc64afc020111::LanaiOperand395*9880d681SAndroid Build Coastguard Worker   void addBrTargetOperands(MCInst &Inst, unsigned N) const {
396*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
397*9880d681SAndroid Build Coastguard Worker     addExpr(Inst, getImm());
398*9880d681SAndroid Build Coastguard Worker   }
399*9880d681SAndroid Build Coastguard Worker 
addCallTargetOperandsllvm::__anonc64afc020111::LanaiOperand400*9880d681SAndroid Build Coastguard Worker   void addCallTargetOperands(MCInst &Inst, unsigned N) const {
401*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
402*9880d681SAndroid Build Coastguard Worker     addExpr(Inst, getImm());
403*9880d681SAndroid Build Coastguard Worker   }
404*9880d681SAndroid Build Coastguard Worker 
addCondCodeOperandsllvm::__anonc64afc020111::LanaiOperand405*9880d681SAndroid Build Coastguard Worker   void addCondCodeOperands(MCInst &Inst, unsigned N) const {
406*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
407*9880d681SAndroid Build Coastguard Worker     addExpr(Inst, getImm());
408*9880d681SAndroid Build Coastguard Worker   }
409*9880d681SAndroid Build Coastguard Worker 
addMemImmOperandsllvm::__anonc64afc020111::LanaiOperand410*9880d681SAndroid Build Coastguard Worker   void addMemImmOperands(MCInst &Inst, unsigned N) const {
411*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
412*9880d681SAndroid Build Coastguard Worker     const MCExpr *Expr = getMemOffset();
413*9880d681SAndroid Build Coastguard Worker     addExpr(Inst, Expr);
414*9880d681SAndroid Build Coastguard Worker   }
415*9880d681SAndroid Build Coastguard Worker 
addMemRegImmOperandsllvm::__anonc64afc020111::LanaiOperand416*9880d681SAndroid Build Coastguard Worker   void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
417*9880d681SAndroid Build Coastguard Worker     assert(N == 3 && "Invalid number of operands!");
418*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
419*9880d681SAndroid Build Coastguard Worker     const MCExpr *Expr = getMemOffset();
420*9880d681SAndroid Build Coastguard Worker     addExpr(Inst, Expr);
421*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(getMemOp()));
422*9880d681SAndroid Build Coastguard Worker   }
423*9880d681SAndroid Build Coastguard Worker 
addMemRegRegOperandsllvm::__anonc64afc020111::LanaiOperand424*9880d681SAndroid Build Coastguard Worker   void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
425*9880d681SAndroid Build Coastguard Worker     assert(N == 3 && "Invalid number of operands!");
426*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
427*9880d681SAndroid Build Coastguard Worker     assert(getMemOffsetReg() != 0 && "Invalid offset");
428*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
429*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(getMemOp()));
430*9880d681SAndroid Build Coastguard Worker   }
431*9880d681SAndroid Build Coastguard Worker 
addMemSplsOperandsllvm::__anonc64afc020111::LanaiOperand432*9880d681SAndroid Build Coastguard Worker   void addMemSplsOperands(MCInst &Inst, unsigned N) const {
433*9880d681SAndroid Build Coastguard Worker     if (isMemRegImm())
434*9880d681SAndroid Build Coastguard Worker       addMemRegImmOperands(Inst, N);
435*9880d681SAndroid Build Coastguard Worker     if (isMemRegReg())
436*9880d681SAndroid Build Coastguard Worker       addMemRegRegOperands(Inst, N);
437*9880d681SAndroid Build Coastguard Worker   }
438*9880d681SAndroid Build Coastguard Worker 
addImmShiftOperandsllvm::__anonc64afc020111::LanaiOperand439*9880d681SAndroid Build Coastguard Worker   void addImmShiftOperands(MCInst &Inst, unsigned N) const {
440*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
441*9880d681SAndroid Build Coastguard Worker     addExpr(Inst, getImm());
442*9880d681SAndroid Build Coastguard Worker   }
443*9880d681SAndroid Build Coastguard Worker 
addImm10Operandsllvm::__anonc64afc020111::LanaiOperand444*9880d681SAndroid Build Coastguard Worker   void addImm10Operands(MCInst &Inst, unsigned N) const {
445*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
446*9880d681SAndroid Build Coastguard Worker     addExpr(Inst, getImm());
447*9880d681SAndroid Build Coastguard Worker   }
448*9880d681SAndroid Build Coastguard Worker 
addLoImm16Operandsllvm::__anonc64afc020111::LanaiOperand449*9880d681SAndroid Build Coastguard Worker   void addLoImm16Operands(MCInst &Inst, unsigned N) const {
450*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
451*9880d681SAndroid Build Coastguard Worker     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
452*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(
453*9880d681SAndroid Build Coastguard Worker           MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
454*9880d681SAndroid Build Coastguard Worker     else if (isa<LanaiMCExpr>(getImm())) {
455*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
456*9880d681SAndroid Build Coastguard Worker       const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
457*9880d681SAndroid Build Coastguard Worker       assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
458*9880d681SAndroid Build Coastguard Worker #endif
459*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(getImm()));
460*9880d681SAndroid Build Coastguard Worker     } else if (isa<MCBinaryExpr>(getImm())) {
461*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
462*9880d681SAndroid Build Coastguard Worker       const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
463*9880d681SAndroid Build Coastguard Worker       assert(dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()) &&
464*9880d681SAndroid Build Coastguard Worker              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
465*9880d681SAndroid Build Coastguard Worker                  LanaiMCExpr::VK_Lanai_ABS_LO);
466*9880d681SAndroid Build Coastguard Worker #endif
467*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(getImm()));
468*9880d681SAndroid Build Coastguard Worker     } else
469*9880d681SAndroid Build Coastguard Worker       assert(false && "Operand type not supported.");
470*9880d681SAndroid Build Coastguard Worker   }
471*9880d681SAndroid Build Coastguard Worker 
addLoImm16AndOperandsllvm::__anonc64afc020111::LanaiOperand472*9880d681SAndroid Build Coastguard Worker   void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
473*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
474*9880d681SAndroid Build Coastguard Worker     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
475*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
476*9880d681SAndroid Build Coastguard Worker     else
477*9880d681SAndroid Build Coastguard Worker       assert(false && "Operand type not supported.");
478*9880d681SAndroid Build Coastguard Worker   }
479*9880d681SAndroid Build Coastguard Worker 
addHiImm16Operandsllvm::__anonc64afc020111::LanaiOperand480*9880d681SAndroid Build Coastguard Worker   void addHiImm16Operands(MCInst &Inst, unsigned N) const {
481*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
482*9880d681SAndroid Build Coastguard Worker     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
483*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
484*9880d681SAndroid Build Coastguard Worker     else if (isa<LanaiMCExpr>(getImm())) {
485*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
486*9880d681SAndroid Build Coastguard Worker       const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
487*9880d681SAndroid Build Coastguard Worker       assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
488*9880d681SAndroid Build Coastguard Worker #endif
489*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(getImm()));
490*9880d681SAndroid Build Coastguard Worker     } else if (isa<MCBinaryExpr>(getImm())) {
491*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
492*9880d681SAndroid Build Coastguard Worker       const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
493*9880d681SAndroid Build Coastguard Worker       assert(dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()) &&
494*9880d681SAndroid Build Coastguard Worker              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
495*9880d681SAndroid Build Coastguard Worker                  LanaiMCExpr::VK_Lanai_ABS_HI);
496*9880d681SAndroid Build Coastguard Worker #endif
497*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(getImm()));
498*9880d681SAndroid Build Coastguard Worker     } else
499*9880d681SAndroid Build Coastguard Worker       assert(false && "Operand type not supported.");
500*9880d681SAndroid Build Coastguard Worker   }
501*9880d681SAndroid Build Coastguard Worker 
addHiImm16AndOperandsllvm::__anonc64afc020111::LanaiOperand502*9880d681SAndroid Build Coastguard Worker   void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
503*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
504*9880d681SAndroid Build Coastguard Worker     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
505*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
506*9880d681SAndroid Build Coastguard Worker     else
507*9880d681SAndroid Build Coastguard Worker       assert(false && "Operand type not supported.");
508*9880d681SAndroid Build Coastguard Worker   }
509*9880d681SAndroid Build Coastguard Worker 
addLoImm21Operandsllvm::__anonc64afc020111::LanaiOperand510*9880d681SAndroid Build Coastguard Worker   void addLoImm21Operands(MCInst &Inst, unsigned N) const {
511*9880d681SAndroid Build Coastguard Worker     assert(N == 1 && "Invalid number of operands!");
512*9880d681SAndroid Build Coastguard Worker     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
513*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
514*9880d681SAndroid Build Coastguard Worker     else if (isa<LanaiMCExpr>(getImm())) {
515*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
516*9880d681SAndroid Build Coastguard Worker       const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
517*9880d681SAndroid Build Coastguard Worker       assert(SymbolRefExpr &&
518*9880d681SAndroid Build Coastguard Worker              SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
519*9880d681SAndroid Build Coastguard Worker #endif
520*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(getImm()));
521*9880d681SAndroid Build Coastguard Worker     } else if (isa<MCSymbolRefExpr>(getImm())) {
522*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
523*9880d681SAndroid Build Coastguard Worker       const MCSymbolRefExpr *SymbolRefExpr =
524*9880d681SAndroid Build Coastguard Worker           dyn_cast<MCSymbolRefExpr>(getImm());
525*9880d681SAndroid Build Coastguard Worker       assert(SymbolRefExpr &&
526*9880d681SAndroid Build Coastguard Worker              SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
527*9880d681SAndroid Build Coastguard Worker #endif
528*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(getImm()));
529*9880d681SAndroid Build Coastguard Worker     } else if (isa<MCBinaryExpr>(getImm())) {
530*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
531*9880d681SAndroid Build Coastguard Worker       const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
532*9880d681SAndroid Build Coastguard Worker       const LanaiMCExpr *SymbolRefExpr =
533*9880d681SAndroid Build Coastguard Worker           dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
534*9880d681SAndroid Build Coastguard Worker       assert(SymbolRefExpr &&
535*9880d681SAndroid Build Coastguard Worker              SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
536*9880d681SAndroid Build Coastguard Worker #endif
537*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(getImm()));
538*9880d681SAndroid Build Coastguard Worker     } else
539*9880d681SAndroid Build Coastguard Worker       assert(false && "Operand type not supported.");
540*9880d681SAndroid Build Coastguard Worker   }
541*9880d681SAndroid Build Coastguard Worker 
printllvm::__anonc64afc020111::LanaiOperand542*9880d681SAndroid Build Coastguard Worker   void print(raw_ostream &OS) const override {
543*9880d681SAndroid Build Coastguard Worker     switch (Kind) {
544*9880d681SAndroid Build Coastguard Worker     case IMMEDIATE:
545*9880d681SAndroid Build Coastguard Worker       OS << "Imm: " << getImm() << "\n";
546*9880d681SAndroid Build Coastguard Worker       break;
547*9880d681SAndroid Build Coastguard Worker     case TOKEN:
548*9880d681SAndroid Build Coastguard Worker       OS << "Token: " << getToken() << "\n";
549*9880d681SAndroid Build Coastguard Worker       break;
550*9880d681SAndroid Build Coastguard Worker     case REGISTER:
551*9880d681SAndroid Build Coastguard Worker       OS << "Reg: %r" << getReg() << "\n";
552*9880d681SAndroid Build Coastguard Worker       break;
553*9880d681SAndroid Build Coastguard Worker     case MEMORY_IMM:
554*9880d681SAndroid Build Coastguard Worker       OS << "MemImm: " << *getMemOffset() << "\n";
555*9880d681SAndroid Build Coastguard Worker       break;
556*9880d681SAndroid Build Coastguard Worker     case MEMORY_REG_IMM:
557*9880d681SAndroid Build Coastguard Worker       OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
558*9880d681SAndroid Build Coastguard Worker       break;
559*9880d681SAndroid Build Coastguard Worker     case MEMORY_REG_REG:
560*9880d681SAndroid Build Coastguard Worker       assert(getMemOffset() == nullptr);
561*9880d681SAndroid Build Coastguard Worker       OS << "MemRegReg: " << getMemBaseReg() << "+"
562*9880d681SAndroid Build Coastguard Worker          << "%r" << getMemOffsetReg() << "\n";
563*9880d681SAndroid Build Coastguard Worker       break;
564*9880d681SAndroid Build Coastguard Worker     }
565*9880d681SAndroid Build Coastguard Worker   }
566*9880d681SAndroid Build Coastguard Worker 
CreateTokenllvm::__anonc64afc020111::LanaiOperand567*9880d681SAndroid Build Coastguard Worker   static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
568*9880d681SAndroid Build Coastguard Worker     auto Op = make_unique<LanaiOperand>(TOKEN);
569*9880d681SAndroid Build Coastguard Worker     Op->Tok.Data = Str.data();
570*9880d681SAndroid Build Coastguard Worker     Op->Tok.Length = Str.size();
571*9880d681SAndroid Build Coastguard Worker     Op->StartLoc = Start;
572*9880d681SAndroid Build Coastguard Worker     Op->EndLoc = Start;
573*9880d681SAndroid Build Coastguard Worker     return Op;
574*9880d681SAndroid Build Coastguard Worker   }
575*9880d681SAndroid Build Coastguard Worker 
createRegllvm::__anonc64afc020111::LanaiOperand576*9880d681SAndroid Build Coastguard Worker   static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start,
577*9880d681SAndroid Build Coastguard Worker                                                  SMLoc End) {
578*9880d681SAndroid Build Coastguard Worker     auto Op = make_unique<LanaiOperand>(REGISTER);
579*9880d681SAndroid Build Coastguard Worker     Op->Reg.RegNum = RegNum;
580*9880d681SAndroid Build Coastguard Worker     Op->StartLoc = Start;
581*9880d681SAndroid Build Coastguard Worker     Op->EndLoc = End;
582*9880d681SAndroid Build Coastguard Worker     return Op;
583*9880d681SAndroid Build Coastguard Worker   }
584*9880d681SAndroid Build Coastguard Worker 
createImmllvm::__anonc64afc020111::LanaiOperand585*9880d681SAndroid Build Coastguard Worker   static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
586*9880d681SAndroid Build Coastguard Worker                                                  SMLoc Start, SMLoc End) {
587*9880d681SAndroid Build Coastguard Worker     auto Op = make_unique<LanaiOperand>(IMMEDIATE);
588*9880d681SAndroid Build Coastguard Worker     Op->Imm.Value = Value;
589*9880d681SAndroid Build Coastguard Worker     Op->StartLoc = Start;
590*9880d681SAndroid Build Coastguard Worker     Op->EndLoc = End;
591*9880d681SAndroid Build Coastguard Worker     return Op;
592*9880d681SAndroid Build Coastguard Worker   }
593*9880d681SAndroid Build Coastguard Worker 
594*9880d681SAndroid Build Coastguard Worker   static std::unique_ptr<LanaiOperand>
MorphToMemImmllvm::__anonc64afc020111::LanaiOperand595*9880d681SAndroid Build Coastguard Worker   MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
596*9880d681SAndroid Build Coastguard Worker     const MCExpr *Imm = Op->getImm();
597*9880d681SAndroid Build Coastguard Worker     Op->Kind = MEMORY_IMM;
598*9880d681SAndroid Build Coastguard Worker     Op->Mem.BaseReg = 0;
599*9880d681SAndroid Build Coastguard Worker     Op->Mem.AluOp = LPAC::ADD;
600*9880d681SAndroid Build Coastguard Worker     Op->Mem.OffsetReg = 0;
601*9880d681SAndroid Build Coastguard Worker     Op->Mem.Offset = Imm;
602*9880d681SAndroid Build Coastguard Worker     return Op;
603*9880d681SAndroid Build Coastguard Worker   }
604*9880d681SAndroid Build Coastguard Worker 
605*9880d681SAndroid Build Coastguard Worker   static std::unique_ptr<LanaiOperand>
MorphToMemRegRegllvm::__anonc64afc020111::LanaiOperand606*9880d681SAndroid Build Coastguard Worker   MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
607*9880d681SAndroid Build Coastguard Worker                    unsigned AluOp) {
608*9880d681SAndroid Build Coastguard Worker     unsigned OffsetReg = Op->getReg();
609*9880d681SAndroid Build Coastguard Worker     Op->Kind = MEMORY_REG_REG;
610*9880d681SAndroid Build Coastguard Worker     Op->Mem.BaseReg = BaseReg;
611*9880d681SAndroid Build Coastguard Worker     Op->Mem.AluOp = AluOp;
612*9880d681SAndroid Build Coastguard Worker     Op->Mem.OffsetReg = OffsetReg;
613*9880d681SAndroid Build Coastguard Worker     Op->Mem.Offset = nullptr;
614*9880d681SAndroid Build Coastguard Worker     return Op;
615*9880d681SAndroid Build Coastguard Worker   }
616*9880d681SAndroid Build Coastguard Worker 
617*9880d681SAndroid Build Coastguard Worker   static std::unique_ptr<LanaiOperand>
MorphToMemRegImmllvm::__anonc64afc020111::LanaiOperand618*9880d681SAndroid Build Coastguard Worker   MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
619*9880d681SAndroid Build Coastguard Worker                    unsigned AluOp) {
620*9880d681SAndroid Build Coastguard Worker     const MCExpr *Imm = Op->getImm();
621*9880d681SAndroid Build Coastguard Worker     Op->Kind = MEMORY_REG_IMM;
622*9880d681SAndroid Build Coastguard Worker     Op->Mem.BaseReg = BaseReg;
623*9880d681SAndroid Build Coastguard Worker     Op->Mem.AluOp = AluOp;
624*9880d681SAndroid Build Coastguard Worker     Op->Mem.OffsetReg = 0;
625*9880d681SAndroid Build Coastguard Worker     Op->Mem.Offset = Imm;
626*9880d681SAndroid Build Coastguard Worker     return Op;
627*9880d681SAndroid Build Coastguard Worker   }
628*9880d681SAndroid Build Coastguard Worker };
629*9880d681SAndroid Build Coastguard Worker 
ParseDirective(AsmToken DirectiveId)630*9880d681SAndroid Build Coastguard Worker bool LanaiAsmParser::ParseDirective(AsmToken DirectiveId) { return true; }
631*9880d681SAndroid Build Coastguard Worker 
MatchAndEmitInstruction(SMLoc IdLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)632*9880d681SAndroid Build Coastguard Worker bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
633*9880d681SAndroid Build Coastguard Worker                                              OperandVector &Operands,
634*9880d681SAndroid Build Coastguard Worker                                              MCStreamer &Out,
635*9880d681SAndroid Build Coastguard Worker                                              uint64_t &ErrorInfo,
636*9880d681SAndroid Build Coastguard Worker                                              bool MatchingInlineAsm) {
637*9880d681SAndroid Build Coastguard Worker   MCInst Inst;
638*9880d681SAndroid Build Coastguard Worker   SMLoc ErrorLoc;
639*9880d681SAndroid Build Coastguard Worker 
640*9880d681SAndroid Build Coastguard Worker   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
641*9880d681SAndroid Build Coastguard Worker   case Match_Success:
642*9880d681SAndroid Build Coastguard Worker     Out.EmitInstruction(Inst, SubtargetInfo);
643*9880d681SAndroid Build Coastguard Worker     return false;
644*9880d681SAndroid Build Coastguard Worker   case Match_MissingFeature:
645*9880d681SAndroid Build Coastguard Worker     return Error(IdLoc, "Instruction use requires option to be enabled");
646*9880d681SAndroid Build Coastguard Worker   case Match_MnemonicFail:
647*9880d681SAndroid Build Coastguard Worker     return Error(IdLoc, "Unrecognized instruction mnemonic");
648*9880d681SAndroid Build Coastguard Worker   case Match_InvalidOperand: {
649*9880d681SAndroid Build Coastguard Worker     ErrorLoc = IdLoc;
650*9880d681SAndroid Build Coastguard Worker     if (ErrorInfo != ~0U) {
651*9880d681SAndroid Build Coastguard Worker       if (ErrorInfo >= Operands.size())
652*9880d681SAndroid Build Coastguard Worker         return Error(IdLoc, "Too few operands for instruction");
653*9880d681SAndroid Build Coastguard Worker 
654*9880d681SAndroid Build Coastguard Worker       ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
655*9880d681SAndroid Build Coastguard Worker       if (ErrorLoc == SMLoc())
656*9880d681SAndroid Build Coastguard Worker         ErrorLoc = IdLoc;
657*9880d681SAndroid Build Coastguard Worker     }
658*9880d681SAndroid Build Coastguard Worker     return Error(ErrorLoc, "Invalid operand for instruction");
659*9880d681SAndroid Build Coastguard Worker   }
660*9880d681SAndroid Build Coastguard Worker   default:
661*9880d681SAndroid Build Coastguard Worker     break;
662*9880d681SAndroid Build Coastguard Worker   }
663*9880d681SAndroid Build Coastguard Worker 
664*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unknown match type detected!");
665*9880d681SAndroid Build Coastguard Worker }
666*9880d681SAndroid Build Coastguard Worker 
667*9880d681SAndroid Build Coastguard Worker // Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
668*9880d681SAndroid Build Coastguard Worker // backwards compatible with GCC and the different ways inline assembly is
669*9880d681SAndroid Build Coastguard Worker // handled.
670*9880d681SAndroid Build Coastguard Worker // TODO: see if there isn't a better way to do this.
parseRegister()671*9880d681SAndroid Build Coastguard Worker std::unique_ptr<LanaiOperand> LanaiAsmParser::parseRegister() {
672*9880d681SAndroid Build Coastguard Worker   SMLoc Start = Parser.getTok().getLoc();
673*9880d681SAndroid Build Coastguard Worker   SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
674*9880d681SAndroid Build Coastguard Worker 
675*9880d681SAndroid Build Coastguard Worker   unsigned RegNum;
676*9880d681SAndroid Build Coastguard Worker   // Eat the '%'.
677*9880d681SAndroid Build Coastguard Worker   if (Lexer.getKind() == AsmToken::Percent)
678*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
679*9880d681SAndroid Build Coastguard Worker   if (Lexer.getKind() == AsmToken::Identifier) {
680*9880d681SAndroid Build Coastguard Worker     RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
681*9880d681SAndroid Build Coastguard Worker     if (RegNum == 0)
682*9880d681SAndroid Build Coastguard Worker       return 0;
683*9880d681SAndroid Build Coastguard Worker     Parser.Lex(); // Eat identifier token
684*9880d681SAndroid Build Coastguard Worker     return LanaiOperand::createReg(RegNum, Start, End);
685*9880d681SAndroid Build Coastguard Worker   }
686*9880d681SAndroid Build Coastguard Worker   return 0;
687*9880d681SAndroid Build Coastguard Worker }
688*9880d681SAndroid Build Coastguard Worker 
ParseRegister(unsigned & RegNum,SMLoc & StartLoc,SMLoc & EndLoc)689*9880d681SAndroid Build Coastguard Worker bool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc,
690*9880d681SAndroid Build Coastguard Worker                                    SMLoc &EndLoc) {
691*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<LanaiOperand> Op = parseRegister();
692*9880d681SAndroid Build Coastguard Worker   if (Op != 0)
693*9880d681SAndroid Build Coastguard Worker     RegNum = Op->getReg();
694*9880d681SAndroid Build Coastguard Worker   return (Op == 0);
695*9880d681SAndroid Build Coastguard Worker }
696*9880d681SAndroid Build Coastguard Worker 
parseIdentifier()697*9880d681SAndroid Build Coastguard Worker std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
698*9880d681SAndroid Build Coastguard Worker   SMLoc Start = Parser.getTok().getLoc();
699*9880d681SAndroid Build Coastguard Worker   SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
700*9880d681SAndroid Build Coastguard Worker   const MCExpr *Res, *RHS = 0;
701*9880d681SAndroid Build Coastguard Worker   LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;
702*9880d681SAndroid Build Coastguard Worker 
703*9880d681SAndroid Build Coastguard Worker   if (Lexer.getKind() != AsmToken::Identifier)
704*9880d681SAndroid Build Coastguard Worker     return 0;
705*9880d681SAndroid Build Coastguard Worker 
706*9880d681SAndroid Build Coastguard Worker   StringRef Identifier;
707*9880d681SAndroid Build Coastguard Worker   if (Parser.parseIdentifier(Identifier))
708*9880d681SAndroid Build Coastguard Worker     return 0;
709*9880d681SAndroid Build Coastguard Worker 
710*9880d681SAndroid Build Coastguard Worker   // Check if identifier has a modifier
711*9880d681SAndroid Build Coastguard Worker   if (Identifier.equals_lower("hi"))
712*9880d681SAndroid Build Coastguard Worker     Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
713*9880d681SAndroid Build Coastguard Worker   else if (Identifier.equals_lower("lo"))
714*9880d681SAndroid Build Coastguard Worker     Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
715*9880d681SAndroid Build Coastguard Worker 
716*9880d681SAndroid Build Coastguard Worker   // If the identifier corresponds to a variant then extract the real
717*9880d681SAndroid Build Coastguard Worker   // identifier.
718*9880d681SAndroid Build Coastguard Worker   if (Kind != LanaiMCExpr::VK_Lanai_None) {
719*9880d681SAndroid Build Coastguard Worker     if (Lexer.getKind() != AsmToken::LParen) {
720*9880d681SAndroid Build Coastguard Worker       Error(Lexer.getLoc(), "Expected '('");
721*9880d681SAndroid Build Coastguard Worker       return 0;
722*9880d681SAndroid Build Coastguard Worker     }
723*9880d681SAndroid Build Coastguard Worker     Lexer.Lex(); // lex '('
724*9880d681SAndroid Build Coastguard Worker 
725*9880d681SAndroid Build Coastguard Worker     // Parse identifier
726*9880d681SAndroid Build Coastguard Worker     if (Parser.parseIdentifier(Identifier))
727*9880d681SAndroid Build Coastguard Worker       return 0;
728*9880d681SAndroid Build Coastguard Worker   }
729*9880d681SAndroid Build Coastguard Worker 
730*9880d681SAndroid Build Coastguard Worker   // If addition parse the RHS.
731*9880d681SAndroid Build Coastguard Worker   if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
732*9880d681SAndroid Build Coastguard Worker     return 0;
733*9880d681SAndroid Build Coastguard Worker 
734*9880d681SAndroid Build Coastguard Worker   // For variants parse the final ')'
735*9880d681SAndroid Build Coastguard Worker   if (Kind != LanaiMCExpr::VK_Lanai_None) {
736*9880d681SAndroid Build Coastguard Worker     if (Lexer.getKind() != AsmToken::RParen) {
737*9880d681SAndroid Build Coastguard Worker       Error(Lexer.getLoc(), "Expected ')'");
738*9880d681SAndroid Build Coastguard Worker       return 0;
739*9880d681SAndroid Build Coastguard Worker     }
740*9880d681SAndroid Build Coastguard Worker     Lexer.Lex(); // lex ')'
741*9880d681SAndroid Build Coastguard Worker   }
742*9880d681SAndroid Build Coastguard Worker 
743*9880d681SAndroid Build Coastguard Worker   End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
744*9880d681SAndroid Build Coastguard Worker   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
745*9880d681SAndroid Build Coastguard Worker   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
746*9880d681SAndroid Build Coastguard Worker   Res = LanaiMCExpr::create(Kind, Expr, getContext());
747*9880d681SAndroid Build Coastguard Worker 
748*9880d681SAndroid Build Coastguard Worker   // Nest if this was an addition
749*9880d681SAndroid Build Coastguard Worker   if (RHS)
750*9880d681SAndroid Build Coastguard Worker     Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
751*9880d681SAndroid Build Coastguard Worker 
752*9880d681SAndroid Build Coastguard Worker   return LanaiOperand::createImm(Res, Start, End);
753*9880d681SAndroid Build Coastguard Worker }
754*9880d681SAndroid Build Coastguard Worker 
parseImmediate()755*9880d681SAndroid Build Coastguard Worker std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
756*9880d681SAndroid Build Coastguard Worker   SMLoc Start = Parser.getTok().getLoc();
757*9880d681SAndroid Build Coastguard Worker   SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
758*9880d681SAndroid Build Coastguard Worker 
759*9880d681SAndroid Build Coastguard Worker   const MCExpr *ExprVal;
760*9880d681SAndroid Build Coastguard Worker   switch (Lexer.getKind()) {
761*9880d681SAndroid Build Coastguard Worker   case AsmToken::Identifier:
762*9880d681SAndroid Build Coastguard Worker     return parseIdentifier();
763*9880d681SAndroid Build Coastguard Worker   case AsmToken::Plus:
764*9880d681SAndroid Build Coastguard Worker   case AsmToken::Minus:
765*9880d681SAndroid Build Coastguard Worker   case AsmToken::Integer:
766*9880d681SAndroid Build Coastguard Worker   case AsmToken::Dot:
767*9880d681SAndroid Build Coastguard Worker     if (!Parser.parseExpression(ExprVal))
768*9880d681SAndroid Build Coastguard Worker       return LanaiOperand::createImm(ExprVal, Start, End);
769*9880d681SAndroid Build Coastguard Worker   default:
770*9880d681SAndroid Build Coastguard Worker     return 0;
771*9880d681SAndroid Build Coastguard Worker   }
772*9880d681SAndroid Build Coastguard Worker }
773*9880d681SAndroid Build Coastguard Worker 
AluWithPrePost(unsigned AluCode,bool PreOp,bool PostOp)774*9880d681SAndroid Build Coastguard Worker static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
775*9880d681SAndroid Build Coastguard Worker   if (PreOp)
776*9880d681SAndroid Build Coastguard Worker     return LPAC::makePreOp(AluCode);
777*9880d681SAndroid Build Coastguard Worker   if (PostOp)
778*9880d681SAndroid Build Coastguard Worker     return LPAC::makePostOp(AluCode);
779*9880d681SAndroid Build Coastguard Worker   return AluCode;
780*9880d681SAndroid Build Coastguard Worker }
781*9880d681SAndroid Build Coastguard Worker 
parseAluOperator(bool PreOp,bool PostOp)782*9880d681SAndroid Build Coastguard Worker unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
783*9880d681SAndroid Build Coastguard Worker   StringRef IdString;
784*9880d681SAndroid Build Coastguard Worker   Parser.parseIdentifier(IdString);
785*9880d681SAndroid Build Coastguard Worker   unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
786*9880d681SAndroid Build Coastguard Worker   if (AluCode == LPAC::UNKNOWN) {
787*9880d681SAndroid Build Coastguard Worker     Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
788*9880d681SAndroid Build Coastguard Worker     return 0;
789*9880d681SAndroid Build Coastguard Worker   }
790*9880d681SAndroid Build Coastguard Worker   return AluCode;
791*9880d681SAndroid Build Coastguard Worker }
792*9880d681SAndroid Build Coastguard Worker 
SizeForSuffix(StringRef T)793*9880d681SAndroid Build Coastguard Worker static int SizeForSuffix(StringRef T) {
794*9880d681SAndroid Build Coastguard Worker   return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
795*9880d681SAndroid Build Coastguard Worker }
796*9880d681SAndroid Build Coastguard Worker 
parsePrePost(StringRef Type,int * OffsetValue)797*9880d681SAndroid Build Coastguard Worker bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
798*9880d681SAndroid Build Coastguard Worker   bool PreOrPost = false;
799*9880d681SAndroid Build Coastguard Worker   if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
800*9880d681SAndroid Build Coastguard Worker     PreOrPost = true;
801*9880d681SAndroid Build Coastguard Worker     if (Lexer.is(AsmToken::Minus))
802*9880d681SAndroid Build Coastguard Worker       *OffsetValue = -SizeForSuffix(Type);
803*9880d681SAndroid Build Coastguard Worker     else if (Lexer.is(AsmToken::Plus))
804*9880d681SAndroid Build Coastguard Worker       *OffsetValue = SizeForSuffix(Type);
805*9880d681SAndroid Build Coastguard Worker     else
806*9880d681SAndroid Build Coastguard Worker       return false;
807*9880d681SAndroid Build Coastguard Worker 
808*9880d681SAndroid Build Coastguard Worker     // Eat the '-' '-' or '+' '+'
809*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
810*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
811*9880d681SAndroid Build Coastguard Worker   } else if (Lexer.is(AsmToken::Star)) {
812*9880d681SAndroid Build Coastguard Worker     Parser.Lex(); // Eat the '*'
813*9880d681SAndroid Build Coastguard Worker     PreOrPost = true;
814*9880d681SAndroid Build Coastguard Worker   }
815*9880d681SAndroid Build Coastguard Worker 
816*9880d681SAndroid Build Coastguard Worker   return PreOrPost;
817*9880d681SAndroid Build Coastguard Worker }
818*9880d681SAndroid Build Coastguard Worker 
shouldBeSls(const LanaiOperand & Op)819*9880d681SAndroid Build Coastguard Worker bool shouldBeSls(const LanaiOperand &Op) {
820*9880d681SAndroid Build Coastguard Worker   // The instruction should be encoded as an SLS if the constant is word
821*9880d681SAndroid Build Coastguard Worker   // aligned and will fit in 21 bits
822*9880d681SAndroid Build Coastguard Worker   if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
823*9880d681SAndroid Build Coastguard Worker     int64_t Value = ConstExpr->getValue();
824*9880d681SAndroid Build Coastguard Worker     return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
825*9880d681SAndroid Build Coastguard Worker   }
826*9880d681SAndroid Build Coastguard Worker   // The instruction should be encoded as an SLS if the operand is a symbolic
827*9880d681SAndroid Build Coastguard Worker   // reference with no variant.
828*9880d681SAndroid Build Coastguard Worker   if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
829*9880d681SAndroid Build Coastguard Worker     return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
830*9880d681SAndroid Build Coastguard Worker   // The instruction should be encoded as an SLS if the operand is a binary
831*9880d681SAndroid Build Coastguard Worker   // expression with the left-hand side being a symbolic reference with no
832*9880d681SAndroid Build Coastguard Worker   // variant.
833*9880d681SAndroid Build Coastguard Worker   if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
834*9880d681SAndroid Build Coastguard Worker     const LanaiMCExpr *LHSSymbolRefExpr =
835*9880d681SAndroid Build Coastguard Worker         dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
836*9880d681SAndroid Build Coastguard Worker     return (LHSSymbolRefExpr &&
837*9880d681SAndroid Build Coastguard Worker             LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
838*9880d681SAndroid Build Coastguard Worker   }
839*9880d681SAndroid Build Coastguard Worker   return false;
840*9880d681SAndroid Build Coastguard Worker }
841*9880d681SAndroid Build Coastguard Worker 
842*9880d681SAndroid Build Coastguard Worker // Matches memory operand. Returns true if error encountered.
843*9880d681SAndroid Build Coastguard Worker LanaiAsmParser::OperandMatchResultTy
parseMemoryOperand(OperandVector & Operands)844*9880d681SAndroid Build Coastguard Worker LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
845*9880d681SAndroid Build Coastguard Worker   // Try to match a memory operand.
846*9880d681SAndroid Build Coastguard Worker   // The memory operands are of the form:
847*9880d681SAndroid Build Coastguard Worker   //  (1)  Register|Immediate|'' '[' '*'? Register '*'? ']' or
848*9880d681SAndroid Build Coastguard Worker   //                            ^
849*9880d681SAndroid Build Coastguard Worker   //  (2)  '[' '*'? Register '*'? AluOperator Register ']'
850*9880d681SAndroid Build Coastguard Worker   //      ^
851*9880d681SAndroid Build Coastguard Worker   //  (3)  '[' '--'|'++' Register '--'|'++' ']'
852*9880d681SAndroid Build Coastguard Worker   //
853*9880d681SAndroid Build Coastguard Worker   //  (4) '[' Immediate ']' (for SLS)
854*9880d681SAndroid Build Coastguard Worker 
855*9880d681SAndroid Build Coastguard Worker   // Store the type for use in parsing pre/post increment/decrement operators
856*9880d681SAndroid Build Coastguard Worker   StringRef Type;
857*9880d681SAndroid Build Coastguard Worker   if (Operands[0]->isToken())
858*9880d681SAndroid Build Coastguard Worker     Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
859*9880d681SAndroid Build Coastguard Worker 
860*9880d681SAndroid Build Coastguard Worker   // Use 0 if no offset given
861*9880d681SAndroid Build Coastguard Worker   int OffsetValue = 0;
862*9880d681SAndroid Build Coastguard Worker   unsigned BaseReg = 0;
863*9880d681SAndroid Build Coastguard Worker   unsigned AluOp = LPAC::ADD;
864*9880d681SAndroid Build Coastguard Worker   bool PostOp = false, PreOp = false;
865*9880d681SAndroid Build Coastguard Worker 
866*9880d681SAndroid Build Coastguard Worker   // Try to parse the offset
867*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<LanaiOperand> Op = parseRegister();
868*9880d681SAndroid Build Coastguard Worker   if (!Op)
869*9880d681SAndroid Build Coastguard Worker     Op = parseImmediate();
870*9880d681SAndroid Build Coastguard Worker 
871*9880d681SAndroid Build Coastguard Worker   // Only continue if next token is '['
872*9880d681SAndroid Build Coastguard Worker   if (Lexer.isNot(AsmToken::LBrac)) {
873*9880d681SAndroid Build Coastguard Worker     if (!Op)
874*9880d681SAndroid Build Coastguard Worker       return MatchOperand_NoMatch;
875*9880d681SAndroid Build Coastguard Worker 
876*9880d681SAndroid Build Coastguard Worker     // The start of this custom parsing overlaps with register/immediate so
877*9880d681SAndroid Build Coastguard Worker     // consider this as a successful match of an operand of that type as the
878*9880d681SAndroid Build Coastguard Worker     // token stream can't be rewound to allow them to match separately.
879*9880d681SAndroid Build Coastguard Worker     Operands.push_back(std::move(Op));
880*9880d681SAndroid Build Coastguard Worker     return MatchOperand_Success;
881*9880d681SAndroid Build Coastguard Worker   }
882*9880d681SAndroid Build Coastguard Worker 
883*9880d681SAndroid Build Coastguard Worker   Parser.Lex(); // Eat the '['.
884*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<LanaiOperand> Offset = nullptr;
885*9880d681SAndroid Build Coastguard Worker   if (Op)
886*9880d681SAndroid Build Coastguard Worker     Offset.swap(Op);
887*9880d681SAndroid Build Coastguard Worker 
888*9880d681SAndroid Build Coastguard Worker   // Determine if a pre operation
889*9880d681SAndroid Build Coastguard Worker   PreOp = parsePrePost(Type, &OffsetValue);
890*9880d681SAndroid Build Coastguard Worker 
891*9880d681SAndroid Build Coastguard Worker   Op = parseRegister();
892*9880d681SAndroid Build Coastguard Worker   if (!Op) {
893*9880d681SAndroid Build Coastguard Worker     if (!Offset) {
894*9880d681SAndroid Build Coastguard Worker       if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
895*9880d681SAndroid Build Coastguard Worker         Parser.Lex(); // Eat the ']'
896*9880d681SAndroid Build Coastguard Worker 
897*9880d681SAndroid Build Coastguard Worker         // Memory address operations aligned to word boundary are encoded as
898*9880d681SAndroid Build Coastguard Worker         // SLS, the rest as RM.
899*9880d681SAndroid Build Coastguard Worker         if (shouldBeSls(*Op)) {
900*9880d681SAndroid Build Coastguard Worker           Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
901*9880d681SAndroid Build Coastguard Worker         } else {
902*9880d681SAndroid Build Coastguard Worker           if (!Op->isLoImm16Signed()) {
903*9880d681SAndroid Build Coastguard Worker             Error(Parser.getTok().getLoc(),
904*9880d681SAndroid Build Coastguard Worker                   "Memory address is not word "
905*9880d681SAndroid Build Coastguard Worker                   "aligned and larger than class RM can handle");
906*9880d681SAndroid Build Coastguard Worker             return MatchOperand_ParseFail;
907*9880d681SAndroid Build Coastguard Worker           }
908*9880d681SAndroid Build Coastguard Worker           Operands.push_back(LanaiOperand::MorphToMemRegImm(
909*9880d681SAndroid Build Coastguard Worker               Lanai::R0, std::move(Op), LPAC::ADD));
910*9880d681SAndroid Build Coastguard Worker         }
911*9880d681SAndroid Build Coastguard Worker         return MatchOperand_Success;
912*9880d681SAndroid Build Coastguard Worker       }
913*9880d681SAndroid Build Coastguard Worker     }
914*9880d681SAndroid Build Coastguard Worker 
915*9880d681SAndroid Build Coastguard Worker     Error(Parser.getTok().getLoc(),
916*9880d681SAndroid Build Coastguard Worker           "Unknown operand, expected register or immediate");
917*9880d681SAndroid Build Coastguard Worker     return MatchOperand_ParseFail;
918*9880d681SAndroid Build Coastguard Worker   }
919*9880d681SAndroid Build Coastguard Worker   BaseReg = Op->getReg();
920*9880d681SAndroid Build Coastguard Worker 
921*9880d681SAndroid Build Coastguard Worker   // Determine if a post operation
922*9880d681SAndroid Build Coastguard Worker   if (!PreOp)
923*9880d681SAndroid Build Coastguard Worker     PostOp = parsePrePost(Type, &OffsetValue);
924*9880d681SAndroid Build Coastguard Worker 
925*9880d681SAndroid Build Coastguard Worker   // If ] match form (1) else match form (2)
926*9880d681SAndroid Build Coastguard Worker   if (Lexer.is(AsmToken::RBrac)) {
927*9880d681SAndroid Build Coastguard Worker     Parser.Lex(); // Eat the ']'.
928*9880d681SAndroid Build Coastguard Worker     if (!Offset) {
929*9880d681SAndroid Build Coastguard Worker       SMLoc Start = Parser.getTok().getLoc();
930*9880d681SAndroid Build Coastguard Worker       SMLoc End =
931*9880d681SAndroid Build Coastguard Worker           SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
932*9880d681SAndroid Build Coastguard Worker       const MCConstantExpr *OffsetConstExpr =
933*9880d681SAndroid Build Coastguard Worker           MCConstantExpr::create(OffsetValue, getContext());
934*9880d681SAndroid Build Coastguard Worker       Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
935*9880d681SAndroid Build Coastguard Worker     }
936*9880d681SAndroid Build Coastguard Worker   } else {
937*9880d681SAndroid Build Coastguard Worker     if (Offset || OffsetValue != 0) {
938*9880d681SAndroid Build Coastguard Worker       Error(Parser.getTok().getLoc(), "Expected ']'");
939*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
940*9880d681SAndroid Build Coastguard Worker     }
941*9880d681SAndroid Build Coastguard Worker 
942*9880d681SAndroid Build Coastguard Worker     // Parse operator
943*9880d681SAndroid Build Coastguard Worker     AluOp = parseAluOperator(PreOp, PostOp);
944*9880d681SAndroid Build Coastguard Worker 
945*9880d681SAndroid Build Coastguard Worker     // Second form requires offset register
946*9880d681SAndroid Build Coastguard Worker     Offset = parseRegister();
947*9880d681SAndroid Build Coastguard Worker     if (!BaseReg || Lexer.isNot(AsmToken::RBrac)) {
948*9880d681SAndroid Build Coastguard Worker       Error(Parser.getTok().getLoc(), "Expected ']'");
949*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
950*9880d681SAndroid Build Coastguard Worker     }
951*9880d681SAndroid Build Coastguard Worker     Parser.Lex(); // Eat the ']'.
952*9880d681SAndroid Build Coastguard Worker   }
953*9880d681SAndroid Build Coastguard Worker 
954*9880d681SAndroid Build Coastguard Worker   // First form has addition as operator. Add pre- or post-op indicator as
955*9880d681SAndroid Build Coastguard Worker   // needed.
956*9880d681SAndroid Build Coastguard Worker   AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
957*9880d681SAndroid Build Coastguard Worker 
958*9880d681SAndroid Build Coastguard Worker   // Ensure immediate offset is not too large
959*9880d681SAndroid Build Coastguard Worker   if (Offset->isImm() && !Offset->isLoImm16Signed()) {
960*9880d681SAndroid Build Coastguard Worker     Error(Parser.getTok().getLoc(),
961*9880d681SAndroid Build Coastguard Worker           "Memory address is not word "
962*9880d681SAndroid Build Coastguard Worker           "aligned and larger than class RM can handle");
963*9880d681SAndroid Build Coastguard Worker     return MatchOperand_ParseFail;
964*9880d681SAndroid Build Coastguard Worker   }
965*9880d681SAndroid Build Coastguard Worker 
966*9880d681SAndroid Build Coastguard Worker   Operands.push_back(
967*9880d681SAndroid Build Coastguard Worker       Offset->isImm()
968*9880d681SAndroid Build Coastguard Worker           ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
969*9880d681SAndroid Build Coastguard Worker           : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
970*9880d681SAndroid Build Coastguard Worker 
971*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
972*9880d681SAndroid Build Coastguard Worker }
973*9880d681SAndroid Build Coastguard Worker 
974*9880d681SAndroid Build Coastguard Worker // Looks at a token type and creates the relevant operand from this
975*9880d681SAndroid Build Coastguard Worker // information, adding to operands.
976*9880d681SAndroid Build Coastguard Worker // If operand was parsed, returns false, else true.
977*9880d681SAndroid Build Coastguard Worker LanaiAsmParser::OperandMatchResultTy
parseOperand(OperandVector * Operands,StringRef Mnemonic)978*9880d681SAndroid Build Coastguard Worker LanaiAsmParser::parseOperand(OperandVector *Operands, StringRef Mnemonic) {
979*9880d681SAndroid Build Coastguard Worker   // Check if the current operand has a custom associated parser, if so, try to
980*9880d681SAndroid Build Coastguard Worker   // custom parse the operand, or fallback to the general approach.
981*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy Result = MatchOperandParserImpl(*Operands, Mnemonic);
982*9880d681SAndroid Build Coastguard Worker 
983*9880d681SAndroid Build Coastguard Worker   if (Result == MatchOperand_Success)
984*9880d681SAndroid Build Coastguard Worker     return Result;
985*9880d681SAndroid Build Coastguard Worker   if (Result == MatchOperand_ParseFail) {
986*9880d681SAndroid Build Coastguard Worker     Parser.eatToEndOfStatement();
987*9880d681SAndroid Build Coastguard Worker     return Result;
988*9880d681SAndroid Build Coastguard Worker   }
989*9880d681SAndroid Build Coastguard Worker 
990*9880d681SAndroid Build Coastguard Worker   // Attempt to parse token as register
991*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<LanaiOperand> Op = parseRegister();
992*9880d681SAndroid Build Coastguard Worker 
993*9880d681SAndroid Build Coastguard Worker   // Attempt to parse token as immediate
994*9880d681SAndroid Build Coastguard Worker   if (!Op)
995*9880d681SAndroid Build Coastguard Worker     Op = parseImmediate();
996*9880d681SAndroid Build Coastguard Worker 
997*9880d681SAndroid Build Coastguard Worker   // If the token could not be parsed then fail
998*9880d681SAndroid Build Coastguard Worker   if (!Op) {
999*9880d681SAndroid Build Coastguard Worker     Error(Parser.getTok().getLoc(), "Unknown operand");
1000*9880d681SAndroid Build Coastguard Worker     Parser.eatToEndOfStatement();
1001*9880d681SAndroid Build Coastguard Worker     return MatchOperand_ParseFail;
1002*9880d681SAndroid Build Coastguard Worker   }
1003*9880d681SAndroid Build Coastguard Worker 
1004*9880d681SAndroid Build Coastguard Worker   // Push back parsed operand into list of operands
1005*9880d681SAndroid Build Coastguard Worker   Operands->push_back(std::move(Op));
1006*9880d681SAndroid Build Coastguard Worker 
1007*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
1008*9880d681SAndroid Build Coastguard Worker }
1009*9880d681SAndroid Build Coastguard Worker 
1010*9880d681SAndroid Build Coastguard Worker // Split the mnemonic into ASM operand, conditional code and instruction
1011*9880d681SAndroid Build Coastguard Worker // qualifier (half-word, byte).
splitMnemonic(StringRef Name,SMLoc NameLoc,OperandVector * Operands)1012*9880d681SAndroid Build Coastguard Worker StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1013*9880d681SAndroid Build Coastguard Worker                                         OperandVector *Operands) {
1014*9880d681SAndroid Build Coastguard Worker   size_t Next = Name.find('.');
1015*9880d681SAndroid Build Coastguard Worker 
1016*9880d681SAndroid Build Coastguard Worker   StringRef Mnemonic = Name;
1017*9880d681SAndroid Build Coastguard Worker 
1018*9880d681SAndroid Build Coastguard Worker   bool IsBRR = false;
1019*9880d681SAndroid Build Coastguard Worker   if (Name.endswith(".r")) {
1020*9880d681SAndroid Build Coastguard Worker     Mnemonic = Name.substr(0, Name.size() - 2);
1021*9880d681SAndroid Build Coastguard Worker     IsBRR = true;
1022*9880d681SAndroid Build Coastguard Worker   }
1023*9880d681SAndroid Build Coastguard Worker 
1024*9880d681SAndroid Build Coastguard Worker   // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1025*9880d681SAndroid Build Coastguard Worker   if (Mnemonic[0] == 'b' ||
1026*9880d681SAndroid Build Coastguard Worker       (Mnemonic[0] == 's' && !Mnemonic.startswith("sel") &&
1027*9880d681SAndroid Build Coastguard Worker        !Mnemonic.startswith("st"))) {
1028*9880d681SAndroid Build Coastguard Worker     // Parse instructions with a conditional code. For example, 'bne' is
1029*9880d681SAndroid Build Coastguard Worker     // converted into two operands 'b' and 'ne'.
1030*9880d681SAndroid Build Coastguard Worker     LPCC::CondCode CondCode =
1031*9880d681SAndroid Build Coastguard Worker         LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1032*9880d681SAndroid Build Coastguard Worker     if (CondCode != LPCC::UNKNOWN) {
1033*9880d681SAndroid Build Coastguard Worker       Mnemonic = Mnemonic.slice(0, 1);
1034*9880d681SAndroid Build Coastguard Worker       Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1035*9880d681SAndroid Build Coastguard Worker       Operands->push_back(LanaiOperand::createImm(
1036*9880d681SAndroid Build Coastguard Worker           MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1037*9880d681SAndroid Build Coastguard Worker       if (IsBRR) {
1038*9880d681SAndroid Build Coastguard Worker         Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1039*9880d681SAndroid Build Coastguard Worker       }
1040*9880d681SAndroid Build Coastguard Worker       return Mnemonic;
1041*9880d681SAndroid Build Coastguard Worker     }
1042*9880d681SAndroid Build Coastguard Worker   }
1043*9880d681SAndroid Build Coastguard Worker 
1044*9880d681SAndroid Build Coastguard Worker   // Parse other instructions with condition codes (RR instructions).
1045*9880d681SAndroid Build Coastguard Worker   // We ignore .f here and assume they are flag-setting operations, not
1046*9880d681SAndroid Build Coastguard Worker   // conditional codes (except for select instructions where flag-setting
1047*9880d681SAndroid Build Coastguard Worker   // variants are not yet implemented).
1048*9880d681SAndroid Build Coastguard Worker   if (Mnemonic.startswith("sel") ||
1049*9880d681SAndroid Build Coastguard Worker       (!Mnemonic.endswith(".f") && !Mnemonic.startswith("st"))) {
1050*9880d681SAndroid Build Coastguard Worker     LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
1051*9880d681SAndroid Build Coastguard Worker     if (CondCode != LPCC::UNKNOWN) {
1052*9880d681SAndroid Build Coastguard Worker       size_t Next = Mnemonic.rfind('.', Name.size());
1053*9880d681SAndroid Build Coastguard Worker       // 'sel' doesn't use a predicate operand whose printer adds the period,
1054*9880d681SAndroid Build Coastguard Worker       // but instead has the period as part of the identifier (i.e., 'sel.' is
1055*9880d681SAndroid Build Coastguard Worker       // expected by the generated matcher). If the mnemonic starts with 'sel'
1056*9880d681SAndroid Build Coastguard Worker       // then include the period as part of the mnemonic, else don't include it
1057*9880d681SAndroid Build Coastguard Worker       // as part of the mnemonic.
1058*9880d681SAndroid Build Coastguard Worker       if (Mnemonic.startswith("sel")) {
1059*9880d681SAndroid Build Coastguard Worker         Mnemonic = Mnemonic.substr(0, Next + 1);
1060*9880d681SAndroid Build Coastguard Worker       } else {
1061*9880d681SAndroid Build Coastguard Worker         Mnemonic = Mnemonic.substr(0, Next);
1062*9880d681SAndroid Build Coastguard Worker       }
1063*9880d681SAndroid Build Coastguard Worker       Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1064*9880d681SAndroid Build Coastguard Worker       Operands->push_back(LanaiOperand::createImm(
1065*9880d681SAndroid Build Coastguard Worker           MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1066*9880d681SAndroid Build Coastguard Worker       return Mnemonic;
1067*9880d681SAndroid Build Coastguard Worker     }
1068*9880d681SAndroid Build Coastguard Worker   }
1069*9880d681SAndroid Build Coastguard Worker 
1070*9880d681SAndroid Build Coastguard Worker   Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1071*9880d681SAndroid Build Coastguard Worker   if (IsBRR) {
1072*9880d681SAndroid Build Coastguard Worker     Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1073*9880d681SAndroid Build Coastguard Worker   }
1074*9880d681SAndroid Build Coastguard Worker 
1075*9880d681SAndroid Build Coastguard Worker   return Mnemonic;
1076*9880d681SAndroid Build Coastguard Worker }
1077*9880d681SAndroid Build Coastguard Worker 
IsMemoryAssignmentError(const OperandVector & Operands)1078*9880d681SAndroid Build Coastguard Worker bool IsMemoryAssignmentError(const OperandVector &Operands) {
1079*9880d681SAndroid Build Coastguard Worker   // Detects if a memory operation has an erroneous base register modification.
1080*9880d681SAndroid Build Coastguard Worker   // Memory operations are detected by matching the types of operands.
1081*9880d681SAndroid Build Coastguard Worker   //
1082*9880d681SAndroid Build Coastguard Worker   // TODO: This test is focussed on one specific instance (ld/st).
1083*9880d681SAndroid Build Coastguard Worker   // Extend it to handle more cases or be more robust.
1084*9880d681SAndroid Build Coastguard Worker   bool Modifies = false;
1085*9880d681SAndroid Build Coastguard Worker 
1086*9880d681SAndroid Build Coastguard Worker   int Offset = 0;
1087*9880d681SAndroid Build Coastguard Worker 
1088*9880d681SAndroid Build Coastguard Worker   if (Operands.size() < 5)
1089*9880d681SAndroid Build Coastguard Worker     return false;
1090*9880d681SAndroid Build Coastguard Worker   else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1091*9880d681SAndroid Build Coastguard Worker            Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1092*9880d681SAndroid Build Coastguard Worker     Offset = 0;
1093*9880d681SAndroid Build Coastguard Worker   else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1094*9880d681SAndroid Build Coastguard Worker            Operands[2]->isReg() && Operands[3]->isImm() &&
1095*9880d681SAndroid Build Coastguard Worker            Operands[4]->isImm() && Operands[5]->isReg())
1096*9880d681SAndroid Build Coastguard Worker     Offset = 1;
1097*9880d681SAndroid Build Coastguard Worker   else
1098*9880d681SAndroid Build Coastguard Worker     return false;
1099*9880d681SAndroid Build Coastguard Worker 
1100*9880d681SAndroid Build Coastguard Worker   int PossibleAluOpIdx = Offset + 3;
1101*9880d681SAndroid Build Coastguard Worker   int PossibleBaseIdx = Offset + 1;
1102*9880d681SAndroid Build Coastguard Worker   int PossibleDestIdx = Offset + 4;
1103*9880d681SAndroid Build Coastguard Worker   if (LanaiOperand *PossibleAluOp =
1104*9880d681SAndroid Build Coastguard Worker           static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1105*9880d681SAndroid Build Coastguard Worker     if (PossibleAluOp->isImm())
1106*9880d681SAndroid Build Coastguard Worker       if (const MCConstantExpr *ConstExpr =
1107*9880d681SAndroid Build Coastguard Worker               dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1108*9880d681SAndroid Build Coastguard Worker         Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1109*9880d681SAndroid Build Coastguard Worker   return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1110*9880d681SAndroid Build Coastguard Worker          Operands[PossibleDestIdx]->isReg() &&
1111*9880d681SAndroid Build Coastguard Worker          Operands[PossibleBaseIdx]->getReg() ==
1112*9880d681SAndroid Build Coastguard Worker              Operands[PossibleDestIdx]->getReg();
1113*9880d681SAndroid Build Coastguard Worker }
1114*9880d681SAndroid Build Coastguard Worker 
IsRegister(const MCParsedAsmOperand & op)1115*9880d681SAndroid Build Coastguard Worker static bool IsRegister(const MCParsedAsmOperand &op) {
1116*9880d681SAndroid Build Coastguard Worker   return static_cast<const LanaiOperand &>(op).isReg();
1117*9880d681SAndroid Build Coastguard Worker }
1118*9880d681SAndroid Build Coastguard Worker 
MaybePredicatedInst(const OperandVector & Operands)1119*9880d681SAndroid Build Coastguard Worker static bool MaybePredicatedInst(const OperandVector &Operands) {
1120*9880d681SAndroid Build Coastguard Worker   if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1121*9880d681SAndroid Build Coastguard Worker       !IsRegister(*Operands[2]))
1122*9880d681SAndroid Build Coastguard Worker     return false;
1123*9880d681SAndroid Build Coastguard Worker   return StringSwitch<bool>(
1124*9880d681SAndroid Build Coastguard Worker              static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1125*9880d681SAndroid Build Coastguard Worker       .StartsWith("addc", true)
1126*9880d681SAndroid Build Coastguard Worker       .StartsWith("add", true)
1127*9880d681SAndroid Build Coastguard Worker       .StartsWith("and", true)
1128*9880d681SAndroid Build Coastguard Worker       .StartsWith("sh", true)
1129*9880d681SAndroid Build Coastguard Worker       .StartsWith("subb", true)
1130*9880d681SAndroid Build Coastguard Worker       .StartsWith("sub", true)
1131*9880d681SAndroid Build Coastguard Worker       .StartsWith("or", true)
1132*9880d681SAndroid Build Coastguard Worker       .StartsWith("xor", true)
1133*9880d681SAndroid Build Coastguard Worker       .Default(false);
1134*9880d681SAndroid Build Coastguard Worker }
1135*9880d681SAndroid Build Coastguard Worker 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)1136*9880d681SAndroid Build Coastguard Worker bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1137*9880d681SAndroid Build Coastguard Worker                                       StringRef Name, SMLoc NameLoc,
1138*9880d681SAndroid Build Coastguard Worker                                       OperandVector &Operands) {
1139*9880d681SAndroid Build Coastguard Worker   // First operand is token for instruction
1140*9880d681SAndroid Build Coastguard Worker   StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1141*9880d681SAndroid Build Coastguard Worker 
1142*9880d681SAndroid Build Coastguard Worker   // If there are no more operands, then finish
1143*9880d681SAndroid Build Coastguard Worker   if (Lexer.is(AsmToken::EndOfStatement))
1144*9880d681SAndroid Build Coastguard Worker     return false;
1145*9880d681SAndroid Build Coastguard Worker 
1146*9880d681SAndroid Build Coastguard Worker   // Parse first operand
1147*9880d681SAndroid Build Coastguard Worker   if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1148*9880d681SAndroid Build Coastguard Worker     return true;
1149*9880d681SAndroid Build Coastguard Worker 
1150*9880d681SAndroid Build Coastguard Worker   // If it is a st instruction with one 1 operand then it is a "store true".
1151*9880d681SAndroid Build Coastguard Worker   // Transform <"st"> to <"s">, <LPCC:ICC_T>
1152*9880d681SAndroid Build Coastguard Worker   if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1153*9880d681SAndroid Build Coastguard Worker       Operands.size() == 2) {
1154*9880d681SAndroid Build Coastguard Worker     Operands.erase(Operands.begin(), Operands.begin() + 1);
1155*9880d681SAndroid Build Coastguard Worker     Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1156*9880d681SAndroid Build Coastguard Worker     Operands.insert(Operands.begin() + 1,
1157*9880d681SAndroid Build Coastguard Worker                     LanaiOperand::createImm(
1158*9880d681SAndroid Build Coastguard Worker                         MCConstantExpr::create(LPCC::ICC_T, getContext()),
1159*9880d681SAndroid Build Coastguard Worker                         NameLoc, NameLoc));
1160*9880d681SAndroid Build Coastguard Worker   }
1161*9880d681SAndroid Build Coastguard Worker 
1162*9880d681SAndroid Build Coastguard Worker   // If the instruction is a bt instruction with 1 operand (in assembly) then it
1163*9880d681SAndroid Build Coastguard Worker   // is an unconditional branch instruction and the first two elements of
1164*9880d681SAndroid Build Coastguard Worker   // operands need to be merged.
1165*9880d681SAndroid Build Coastguard Worker   if (Lexer.is(AsmToken::EndOfStatement) && Name.startswith("bt") &&
1166*9880d681SAndroid Build Coastguard Worker       Operands.size() == 3) {
1167*9880d681SAndroid Build Coastguard Worker     Operands.erase(Operands.begin(), Operands.begin() + 2);
1168*9880d681SAndroid Build Coastguard Worker     Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1169*9880d681SAndroid Build Coastguard Worker   }
1170*9880d681SAndroid Build Coastguard Worker 
1171*9880d681SAndroid Build Coastguard Worker   // Parse until end of statement, consuming commas between operands
1172*9880d681SAndroid Build Coastguard Worker   while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1173*9880d681SAndroid Build Coastguard Worker     // Consume comma token
1174*9880d681SAndroid Build Coastguard Worker     Lex();
1175*9880d681SAndroid Build Coastguard Worker 
1176*9880d681SAndroid Build Coastguard Worker     // Parse next operand
1177*9880d681SAndroid Build Coastguard Worker     if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1178*9880d681SAndroid Build Coastguard Worker       return true;
1179*9880d681SAndroid Build Coastguard Worker   }
1180*9880d681SAndroid Build Coastguard Worker 
1181*9880d681SAndroid Build Coastguard Worker   if (IsMemoryAssignmentError(Operands)) {
1182*9880d681SAndroid Build Coastguard Worker     Error(Parser.getTok().getLoc(),
1183*9880d681SAndroid Build Coastguard Worker           "the destination register can't equal the base register in an "
1184*9880d681SAndroid Build Coastguard Worker           "instruction that modifies the base register.");
1185*9880d681SAndroid Build Coastguard Worker     return true;
1186*9880d681SAndroid Build Coastguard Worker   }
1187*9880d681SAndroid Build Coastguard Worker 
1188*9880d681SAndroid Build Coastguard Worker   // Insert always true operand for instruction that may be predicated but
1189*9880d681SAndroid Build Coastguard Worker   // are not. Currently the autogenerated parser always expects a predicate.
1190*9880d681SAndroid Build Coastguard Worker   if (MaybePredicatedInst(Operands)) {
1191*9880d681SAndroid Build Coastguard Worker     Operands.insert(Operands.begin() + 1,
1192*9880d681SAndroid Build Coastguard Worker                     LanaiOperand::createImm(
1193*9880d681SAndroid Build Coastguard Worker                         MCConstantExpr::create(LPCC::ICC_T, getContext()),
1194*9880d681SAndroid Build Coastguard Worker                         NameLoc, NameLoc));
1195*9880d681SAndroid Build Coastguard Worker   }
1196*9880d681SAndroid Build Coastguard Worker 
1197*9880d681SAndroid Build Coastguard Worker   return false;
1198*9880d681SAndroid Build Coastguard Worker }
1199*9880d681SAndroid Build Coastguard Worker 
1200*9880d681SAndroid Build Coastguard Worker #define GET_REGISTER_MATCHER
1201*9880d681SAndroid Build Coastguard Worker #define GET_MATCHER_IMPLEMENTATION
1202*9880d681SAndroid Build Coastguard Worker #include "LanaiGenAsmMatcher.inc"
1203*9880d681SAndroid Build Coastguard Worker } // namespace
1204*9880d681SAndroid Build Coastguard Worker 
LLVMInitializeLanaiAsmParser()1205*9880d681SAndroid Build Coastguard Worker extern "C" void LLVMInitializeLanaiAsmParser() {
1206*9880d681SAndroid Build Coastguard Worker   RegisterMCAsmParser<LanaiAsmParser> x(TheLanaiTarget);
1207*9880d681SAndroid Build Coastguard Worker }
1208*9880d681SAndroid Build Coastguard Worker 
1209*9880d681SAndroid Build Coastguard Worker } // namespace llvm
1210