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