xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1*349cc55cSDimitry Andric //===---- CSKYAsmParser.cpp - Parse CSKY assembly to MCInst instructions --===//
2fe6060f1SDimitry Andric //
3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric 
9*349cc55cSDimitry Andric #include "MCTargetDesc/CSKYInstPrinter.h"
10fe6060f1SDimitry Andric #include "MCTargetDesc/CSKYMCExpr.h"
11fe6060f1SDimitry Andric #include "MCTargetDesc/CSKYMCTargetDesc.h"
12fe6060f1SDimitry Andric #include "TargetInfo/CSKYTargetInfo.h"
13fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h"
14fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
15fe6060f1SDimitry Andric #include "llvm/CodeGen/Register.h"
16fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h"
17fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h"
18fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h"
19fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
20fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
22fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
23*349cc55cSDimitry Andric #include "llvm/MC/MCSectionELF.h"
24fe6060f1SDimitry Andric #include "llvm/MC/MCStreamer.h"
25fe6060f1SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
26*349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
27fe6060f1SDimitry Andric #include "llvm/Support/Casting.h"
28*349cc55cSDimitry Andric #include "llvm/Support/Debug.h"
29*349cc55cSDimitry Andric 
30*349cc55cSDimitry Andric #define DEBUG_TYPE "csky-asm-parser"
31fe6060f1SDimitry Andric 
32fe6060f1SDimitry Andric using namespace llvm;
33fe6060f1SDimitry Andric 
34fe6060f1SDimitry Andric namespace {
35fe6060f1SDimitry Andric struct CSKYOperand;
36fe6060f1SDimitry Andric 
37fe6060f1SDimitry Andric class CSKYAsmParser : public MCTargetAsmParser {
38fe6060f1SDimitry Andric 
39*349cc55cSDimitry Andric   const MCRegisterInfo *MRI;
40*349cc55cSDimitry Andric 
41fe6060f1SDimitry Andric   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
42fe6060f1SDimitry Andric                                   int64_t Lower, int64_t Upper, Twine Msg);
43fe6060f1SDimitry Andric 
44fe6060f1SDimitry Andric   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
45fe6060f1SDimitry Andric 
46fe6060f1SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
47fe6060f1SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
48fe6060f1SDimitry Andric                                uint64_t &ErrorInfo,
49fe6060f1SDimitry Andric                                bool MatchingInlineAsm) override;
50fe6060f1SDimitry Andric 
51fe6060f1SDimitry Andric   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
52fe6060f1SDimitry Andric 
53fe6060f1SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
54fe6060f1SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
55fe6060f1SDimitry Andric 
56fe6060f1SDimitry Andric   bool ParseDirective(AsmToken DirectiveID) override;
57fe6060f1SDimitry Andric 
58fe6060f1SDimitry Andric   OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
59fe6060f1SDimitry Andric                                         SMLoc &EndLoc) override;
60fe6060f1SDimitry Andric 
61*349cc55cSDimitry Andric   bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
62*349cc55cSDimitry Andric                           MCStreamer &Out);
63*349cc55cSDimitry Andric 
64fe6060f1SDimitry Andric // Auto-generated instruction matching functions
65fe6060f1SDimitry Andric #define GET_ASSEMBLER_HEADER
66fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
67fe6060f1SDimitry Andric 
68fe6060f1SDimitry Andric   OperandMatchResultTy parseImmediate(OperandVector &Operands);
69fe6060f1SDimitry Andric   OperandMatchResultTy parseRegister(OperandVector &Operands);
70fe6060f1SDimitry Andric   OperandMatchResultTy parseBaseRegImm(OperandVector &Operands);
71fe6060f1SDimitry Andric   OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands);
72fe6060f1SDimitry Andric   OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands);
73*349cc55cSDimitry Andric   OperandMatchResultTy parseDataSymbol(OperandVector &Operands);
74*349cc55cSDimitry Andric   OperandMatchResultTy parsePSRFlag(OperandVector &Operands);
75*349cc55cSDimitry Andric   OperandMatchResultTy parseRegSeq(OperandVector &Operands);
76*349cc55cSDimitry Andric   OperandMatchResultTy parseRegList(OperandVector &Operands);
77fe6060f1SDimitry Andric 
78fe6060f1SDimitry Andric   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
79fe6060f1SDimitry Andric 
80fe6060f1SDimitry Andric public:
81fe6060f1SDimitry Andric   enum CSKYMatchResultTy {
82fe6060f1SDimitry Andric     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
83*349cc55cSDimitry Andric     Match_RequiresSameSrcAndDst,
84*349cc55cSDimitry Andric     Match_InvalidRegOutOfRange,
85fe6060f1SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
86fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
87fe6060f1SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES
88fe6060f1SDimitry Andric   };
89fe6060f1SDimitry Andric 
90fe6060f1SDimitry Andric   CSKYAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
91fe6060f1SDimitry Andric                 const MCInstrInfo &MII, const MCTargetOptions &Options)
92fe6060f1SDimitry Andric       : MCTargetAsmParser(Options, STI, MII) {
93fe6060f1SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
94fe6060f1SDimitry Andric   }
95fe6060f1SDimitry Andric };
96fe6060f1SDimitry Andric 
97fe6060f1SDimitry Andric /// Instances of this class represent a parsed machine instruction.
98fe6060f1SDimitry Andric struct CSKYOperand : public MCParsedAsmOperand {
99*349cc55cSDimitry Andric 
100fe6060f1SDimitry Andric   enum KindTy {
101fe6060f1SDimitry Andric     Token,
102fe6060f1SDimitry Andric     Register,
103fe6060f1SDimitry Andric     Immediate,
104*349cc55cSDimitry Andric     RegisterSeq,
105*349cc55cSDimitry Andric     CPOP,
106*349cc55cSDimitry Andric     RegisterList
107fe6060f1SDimitry Andric   } Kind;
108fe6060f1SDimitry Andric 
109fe6060f1SDimitry Andric   struct RegOp {
110fe6060f1SDimitry Andric     unsigned RegNum;
111fe6060f1SDimitry Andric   };
112fe6060f1SDimitry Andric 
113fe6060f1SDimitry Andric   struct ImmOp {
114fe6060f1SDimitry Andric     const MCExpr *Val;
115fe6060f1SDimitry Andric   };
116fe6060f1SDimitry Andric 
117*349cc55cSDimitry Andric   struct ConstpoolOp {
118*349cc55cSDimitry Andric     const MCExpr *Val;
119*349cc55cSDimitry Andric   };
120*349cc55cSDimitry Andric 
121*349cc55cSDimitry Andric   struct RegSeqOp {
122*349cc55cSDimitry Andric     unsigned RegNumFrom;
123*349cc55cSDimitry Andric     unsigned RegNumTo;
124*349cc55cSDimitry Andric   };
125*349cc55cSDimitry Andric 
126*349cc55cSDimitry Andric   struct RegListOp {
127*349cc55cSDimitry Andric     unsigned List1From = 0;
128*349cc55cSDimitry Andric     unsigned List1To = 0;
129*349cc55cSDimitry Andric     unsigned List2From = 0;
130*349cc55cSDimitry Andric     unsigned List2To = 0;
131*349cc55cSDimitry Andric     unsigned List3From = 0;
132*349cc55cSDimitry Andric     unsigned List3To = 0;
133*349cc55cSDimitry Andric     unsigned List4From = 0;
134*349cc55cSDimitry Andric     unsigned List4To = 0;
135*349cc55cSDimitry Andric   };
136*349cc55cSDimitry Andric 
137fe6060f1SDimitry Andric   SMLoc StartLoc, EndLoc;
138fe6060f1SDimitry Andric   union {
139fe6060f1SDimitry Andric     StringRef Tok;
140fe6060f1SDimitry Andric     RegOp Reg;
141fe6060f1SDimitry Andric     ImmOp Imm;
142*349cc55cSDimitry Andric     ConstpoolOp CPool;
143*349cc55cSDimitry Andric     RegSeqOp RegSeq;
144*349cc55cSDimitry Andric     RegListOp RegList;
145fe6060f1SDimitry Andric   };
146fe6060f1SDimitry Andric 
147fe6060f1SDimitry Andric   CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
148fe6060f1SDimitry Andric 
149fe6060f1SDimitry Andric public:
150fe6060f1SDimitry Andric   CSKYOperand(const CSKYOperand &o) : MCParsedAsmOperand() {
151fe6060f1SDimitry Andric     Kind = o.Kind;
152fe6060f1SDimitry Andric     StartLoc = o.StartLoc;
153fe6060f1SDimitry Andric     EndLoc = o.EndLoc;
154fe6060f1SDimitry Andric     switch (Kind) {
155fe6060f1SDimitry Andric     case Register:
156fe6060f1SDimitry Andric       Reg = o.Reg;
157fe6060f1SDimitry Andric       break;
158*349cc55cSDimitry Andric     case RegisterSeq:
159*349cc55cSDimitry Andric       RegSeq = o.RegSeq;
160*349cc55cSDimitry Andric       break;
161*349cc55cSDimitry Andric     case CPOP:
162*349cc55cSDimitry Andric       CPool = o.CPool;
163*349cc55cSDimitry Andric       break;
164fe6060f1SDimitry Andric     case Immediate:
165fe6060f1SDimitry Andric       Imm = o.Imm;
166fe6060f1SDimitry Andric       break;
167fe6060f1SDimitry Andric     case Token:
168fe6060f1SDimitry Andric       Tok = o.Tok;
169fe6060f1SDimitry Andric       break;
170*349cc55cSDimitry Andric     case RegisterList:
171*349cc55cSDimitry Andric       RegList = o.RegList;
172*349cc55cSDimitry Andric       break;
173fe6060f1SDimitry Andric     }
174fe6060f1SDimitry Andric   }
175fe6060f1SDimitry Andric 
176fe6060f1SDimitry Andric   bool isToken() const override { return Kind == Token; }
177fe6060f1SDimitry Andric   bool isReg() const override { return Kind == Register; }
178fe6060f1SDimitry Andric   bool isImm() const override { return Kind == Immediate; }
179*349cc55cSDimitry Andric   bool isRegisterSeq() const { return Kind == RegisterSeq; }
180*349cc55cSDimitry Andric   bool isRegisterList() const { return Kind == RegisterList; }
181*349cc55cSDimitry Andric   bool isConstPoolOp() const { return Kind == CPOP; }
182*349cc55cSDimitry Andric 
183fe6060f1SDimitry Andric   bool isMem() const override { return false; }
184fe6060f1SDimitry Andric 
185fe6060f1SDimitry Andric   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
186fe6060f1SDimitry Andric     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
187fe6060f1SDimitry Andric       Imm = CE->getValue();
188fe6060f1SDimitry Andric       return true;
189fe6060f1SDimitry Andric     }
190fe6060f1SDimitry Andric 
191fe6060f1SDimitry Andric     return false;
192fe6060f1SDimitry Andric   }
193fe6060f1SDimitry Andric 
194fe6060f1SDimitry Andric   template <unsigned num, unsigned shift = 0> bool isUImm() const {
195fe6060f1SDimitry Andric     if (!isImm())
196fe6060f1SDimitry Andric       return false;
197fe6060f1SDimitry Andric 
198fe6060f1SDimitry Andric     int64_t Imm;
199fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
200fe6060f1SDimitry Andric     return IsConstantImm && isShiftedUInt<num, shift>(Imm);
201fe6060f1SDimitry Andric   }
202fe6060f1SDimitry Andric 
203fe6060f1SDimitry Andric   template <unsigned num> bool isOImm() const {
204fe6060f1SDimitry Andric     if (!isImm())
205fe6060f1SDimitry Andric       return false;
206fe6060f1SDimitry Andric 
207fe6060f1SDimitry Andric     int64_t Imm;
208fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
209fe6060f1SDimitry Andric     return IsConstantImm && isUInt<num>(Imm - 1);
210fe6060f1SDimitry Andric   }
211fe6060f1SDimitry Andric 
212fe6060f1SDimitry Andric   template <unsigned num, unsigned shift = 0> bool isSImm() const {
213fe6060f1SDimitry Andric     if (!isImm())
214fe6060f1SDimitry Andric       return false;
215fe6060f1SDimitry Andric 
216fe6060f1SDimitry Andric     int64_t Imm;
217fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
218fe6060f1SDimitry Andric     return IsConstantImm && isShiftedInt<num, shift>(Imm);
219fe6060f1SDimitry Andric   }
220fe6060f1SDimitry Andric 
221*349cc55cSDimitry Andric   bool isUImm1() const { return isUImm<1>(); }
222fe6060f1SDimitry Andric   bool isUImm2() const { return isUImm<2>(); }
223*349cc55cSDimitry Andric   bool isUImm3() const { return isUImm<3>(); }
224*349cc55cSDimitry Andric   bool isUImm4() const { return isUImm<4>(); }
225fe6060f1SDimitry Andric   bool isUImm5() const { return isUImm<5>(); }
226*349cc55cSDimitry Andric   bool isUImm6() const { return isUImm<6>(); }
227*349cc55cSDimitry Andric   bool isUImm7() const { return isUImm<7>(); }
228*349cc55cSDimitry Andric   bool isUImm8() const { return isUImm<8>(); }
229fe6060f1SDimitry Andric   bool isUImm12() const { return isUImm<12>(); }
230fe6060f1SDimitry Andric   bool isUImm16() const { return isUImm<16>(); }
231*349cc55cSDimitry Andric   bool isUImm20() const { return isUImm<20>(); }
232*349cc55cSDimitry Andric   bool isUImm24() const { return isUImm<24>(); }
233fe6060f1SDimitry Andric 
234*349cc55cSDimitry Andric   bool isOImm3() const { return isOImm<3>(); }
235*349cc55cSDimitry Andric   bool isOImm4() const { return isOImm<4>(); }
236*349cc55cSDimitry Andric   bool isOImm5() const { return isOImm<5>(); }
237*349cc55cSDimitry Andric   bool isOImm6() const { return isOImm<6>(); }
238*349cc55cSDimitry Andric   bool isOImm8() const { return isOImm<8>(); }
239fe6060f1SDimitry Andric   bool isOImm12() const { return isOImm<12>(); }
240fe6060f1SDimitry Andric   bool isOImm16() const { return isOImm<16>(); }
241fe6060f1SDimitry Andric 
242*349cc55cSDimitry Andric   bool isSImm8() const { return isSImm<8>(); }
243*349cc55cSDimitry Andric 
244*349cc55cSDimitry Andric   bool isUImm5Shift1() { return isUImm<5, 1>(); }
245*349cc55cSDimitry Andric   bool isUImm5Shift2() { return isUImm<5, 2>(); }
246*349cc55cSDimitry Andric   bool isUImm7Shift1() { return isUImm<7, 1>(); }
247*349cc55cSDimitry Andric   bool isUImm7Shift2() { return isUImm<7, 2>(); }
248*349cc55cSDimitry Andric   bool isUImm7Shift3() { return isUImm<7, 3>(); }
249*349cc55cSDimitry Andric   bool isUImm8Shift2() { return isUImm<8, 2>(); }
250*349cc55cSDimitry Andric   bool isUImm8Shift3() { return isUImm<8, 3>(); }
251*349cc55cSDimitry Andric   bool isUImm8Shift8() { return isUImm<8, 8>(); }
252*349cc55cSDimitry Andric   bool isUImm8Shift16() { return isUImm<8, 16>(); }
253*349cc55cSDimitry Andric   bool isUImm8Shift24() { return isUImm<8, 24>(); }
254fe6060f1SDimitry Andric   bool isUImm12Shift1() { return isUImm<12, 1>(); }
255fe6060f1SDimitry Andric   bool isUImm12Shift2() { return isUImm<12, 2>(); }
256*349cc55cSDimitry Andric   bool isUImm16Shift8() { return isUImm<16, 8>(); }
257*349cc55cSDimitry Andric   bool isUImm16Shift16() { return isUImm<16, 16>(); }
258*349cc55cSDimitry Andric   bool isUImm24Shift8() { return isUImm<24, 8>(); }
259fe6060f1SDimitry Andric 
260fe6060f1SDimitry Andric   bool isSImm16Shift1() { return isSImm<16, 1>(); }
261fe6060f1SDimitry Andric 
262*349cc55cSDimitry Andric   bool isCSKYSymbol() const { return isImm(); }
263*349cc55cSDimitry Andric 
264*349cc55cSDimitry Andric   bool isConstpool() const { return isConstPoolOp(); }
265*349cc55cSDimitry Andric   bool isDataSymbol() const { return isConstPoolOp(); }
266*349cc55cSDimitry Andric 
267*349cc55cSDimitry Andric   bool isSPOperand() const {
268*349cc55cSDimitry Andric     if (!isReg())
269*349cc55cSDimitry Andric       return false;
270*349cc55cSDimitry Andric     return getReg() == CSKY::R14;
271fe6060f1SDimitry Andric   }
272fe6060f1SDimitry Andric 
273*349cc55cSDimitry Andric   bool isPSRFlag() const {
274fe6060f1SDimitry Andric     int64_t Imm;
275*349cc55cSDimitry Andric     // Must be of 'immediate' type and a constant.
276*349cc55cSDimitry Andric     if (!isImm() || !evaluateConstantImm(getImm(), Imm))
277*349cc55cSDimitry Andric       return false;
278*349cc55cSDimitry Andric 
279*349cc55cSDimitry Andric     return isUInt<5>(Imm);
280*349cc55cSDimitry Andric   }
281*349cc55cSDimitry Andric 
282*349cc55cSDimitry Andric   template <unsigned MIN, unsigned MAX> bool isRegSeqTemplate() const {
283*349cc55cSDimitry Andric     if (!isRegisterSeq())
284*349cc55cSDimitry Andric       return false;
285*349cc55cSDimitry Andric 
286*349cc55cSDimitry Andric     std::pair<unsigned, unsigned> regSeq = getRegSeq();
287*349cc55cSDimitry Andric 
288*349cc55cSDimitry Andric     return MIN <= regSeq.first && regSeq.first <= regSeq.second &&
289*349cc55cSDimitry Andric            regSeq.second <= MAX;
290*349cc55cSDimitry Andric   }
291*349cc55cSDimitry Andric 
292*349cc55cSDimitry Andric   bool isRegSeq() const { return isRegSeqTemplate<CSKY::R0, CSKY::R31>(); }
293*349cc55cSDimitry Andric 
294*349cc55cSDimitry Andric   static bool isLegalRegList(unsigned from, unsigned to) {
295*349cc55cSDimitry Andric     if (from == 0 && to == 0)
296*349cc55cSDimitry Andric       return true;
297*349cc55cSDimitry Andric 
298*349cc55cSDimitry Andric     if (from == to) {
299*349cc55cSDimitry Andric       if (from != CSKY::R4 && from != CSKY::R15 && from != CSKY::R16 &&
300*349cc55cSDimitry Andric           from != CSKY::R28)
301*349cc55cSDimitry Andric         return false;
302*349cc55cSDimitry Andric 
303*349cc55cSDimitry Andric       return true;
304*349cc55cSDimitry Andric     } else {
305*349cc55cSDimitry Andric       if (from != CSKY::R4 && from != CSKY::R16)
306*349cc55cSDimitry Andric         return false;
307*349cc55cSDimitry Andric 
308*349cc55cSDimitry Andric       if (from == CSKY::R4 && to > CSKY::R4 && to < CSKY::R12)
309*349cc55cSDimitry Andric         return true;
310*349cc55cSDimitry Andric       else if (from == CSKY::R16 && to > CSKY::R16 && to < CSKY::R18)
311*349cc55cSDimitry Andric         return true;
312*349cc55cSDimitry Andric       else
313*349cc55cSDimitry Andric         return false;
314*349cc55cSDimitry Andric     }
315*349cc55cSDimitry Andric   }
316*349cc55cSDimitry Andric 
317*349cc55cSDimitry Andric   bool isRegList() const {
318*349cc55cSDimitry Andric     if (!isRegisterList())
319*349cc55cSDimitry Andric       return false;
320*349cc55cSDimitry Andric 
321*349cc55cSDimitry Andric     auto regList = getRegList();
322*349cc55cSDimitry Andric 
323*349cc55cSDimitry Andric     if (!isLegalRegList(regList.List1From, regList.List1To))
324*349cc55cSDimitry Andric       return false;
325*349cc55cSDimitry Andric     if (!isLegalRegList(regList.List2From, regList.List2To))
326*349cc55cSDimitry Andric       return false;
327*349cc55cSDimitry Andric     if (!isLegalRegList(regList.List3From, regList.List3To))
328*349cc55cSDimitry Andric       return false;
329*349cc55cSDimitry Andric     if (!isLegalRegList(regList.List4From, regList.List4To))
330*349cc55cSDimitry Andric       return false;
331*349cc55cSDimitry Andric 
332*349cc55cSDimitry Andric     return true;
333*349cc55cSDimitry Andric   }
334*349cc55cSDimitry Andric 
335*349cc55cSDimitry Andric   bool isExtImm6() {
336*349cc55cSDimitry Andric     if (!isImm())
337*349cc55cSDimitry Andric       return false;
338*349cc55cSDimitry Andric 
339*349cc55cSDimitry Andric     int64_t Imm;
340*349cc55cSDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
341*349cc55cSDimitry Andric     if (!IsConstantImm)
342*349cc55cSDimitry Andric       return false;
343*349cc55cSDimitry Andric 
344*349cc55cSDimitry Andric     int uimm4 = Imm & 0xf;
345*349cc55cSDimitry Andric 
346*349cc55cSDimitry Andric     return isShiftedUInt<6, 0>(Imm) && uimm4 >= 0 && uimm4 <= 14;
347fe6060f1SDimitry Andric   }
348fe6060f1SDimitry Andric 
349fe6060f1SDimitry Andric   /// Gets location of the first token of this operand.
350fe6060f1SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
351fe6060f1SDimitry Andric   /// Gets location of the last token of this operand.
352fe6060f1SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
353fe6060f1SDimitry Andric 
354fe6060f1SDimitry Andric   unsigned getReg() const override {
355fe6060f1SDimitry Andric     assert(Kind == Register && "Invalid type access!");
356fe6060f1SDimitry Andric     return Reg.RegNum;
357fe6060f1SDimitry Andric   }
358fe6060f1SDimitry Andric 
359*349cc55cSDimitry Andric   std::pair<unsigned, unsigned> getRegSeq() const {
360*349cc55cSDimitry Andric     assert(Kind == RegisterSeq && "Invalid type access!");
361*349cc55cSDimitry Andric     return std::pair<unsigned, unsigned>(RegSeq.RegNumFrom, RegSeq.RegNumTo);
362*349cc55cSDimitry Andric   }
363*349cc55cSDimitry Andric 
364*349cc55cSDimitry Andric   RegListOp getRegList() const {
365*349cc55cSDimitry Andric     assert(Kind == RegisterList && "Invalid type access!");
366*349cc55cSDimitry Andric     return RegList;
367*349cc55cSDimitry Andric   }
368*349cc55cSDimitry Andric 
369fe6060f1SDimitry Andric   const MCExpr *getImm() const {
370fe6060f1SDimitry Andric     assert(Kind == Immediate && "Invalid type access!");
371fe6060f1SDimitry Andric     return Imm.Val;
372fe6060f1SDimitry Andric   }
373fe6060f1SDimitry Andric 
374*349cc55cSDimitry Andric   const MCExpr *getConstpoolOp() const {
375*349cc55cSDimitry Andric     assert(Kind == CPOP && "Invalid type access!");
376*349cc55cSDimitry Andric     return CPool.Val;
377*349cc55cSDimitry Andric   }
378*349cc55cSDimitry Andric 
379fe6060f1SDimitry Andric   StringRef getToken() const {
380fe6060f1SDimitry Andric     assert(Kind == Token && "Invalid type access!");
381fe6060f1SDimitry Andric     return Tok;
382fe6060f1SDimitry Andric   }
383fe6060f1SDimitry Andric 
384fe6060f1SDimitry Andric   void print(raw_ostream &OS) const override {
385*349cc55cSDimitry Andric     auto RegName = [](unsigned Reg) {
386*349cc55cSDimitry Andric       if (Reg)
387*349cc55cSDimitry Andric         return CSKYInstPrinter::getRegisterName(Reg);
388*349cc55cSDimitry Andric       else
389*349cc55cSDimitry Andric         return "noreg";
390*349cc55cSDimitry Andric     };
391*349cc55cSDimitry Andric 
392fe6060f1SDimitry Andric     switch (Kind) {
393*349cc55cSDimitry Andric     case CPOP:
394*349cc55cSDimitry Andric       OS << *getConstpoolOp();
395*349cc55cSDimitry Andric       break;
396fe6060f1SDimitry Andric     case Immediate:
397fe6060f1SDimitry Andric       OS << *getImm();
398fe6060f1SDimitry Andric       break;
399*349cc55cSDimitry Andric     case KindTy::Register:
400*349cc55cSDimitry Andric       OS << "<register " << RegName(getReg()) << ">";
401*349cc55cSDimitry Andric       break;
402*349cc55cSDimitry Andric     case RegisterSeq:
403*349cc55cSDimitry Andric       OS << "<register-seq ";
404*349cc55cSDimitry Andric       OS << RegName(getRegSeq().first) << "-" << RegName(getRegSeq().second)
405*349cc55cSDimitry Andric          << ">";
406*349cc55cSDimitry Andric       break;
407*349cc55cSDimitry Andric     case RegisterList:
408*349cc55cSDimitry Andric       OS << "<register-list ";
409*349cc55cSDimitry Andric       OS << RegName(getRegList().List1From) << "-"
410*349cc55cSDimitry Andric          << RegName(getRegList().List1To) << ",";
411*349cc55cSDimitry Andric       OS << RegName(getRegList().List2From) << "-"
412*349cc55cSDimitry Andric          << RegName(getRegList().List2To) << ",";
413*349cc55cSDimitry Andric       OS << RegName(getRegList().List3From) << "-"
414*349cc55cSDimitry Andric          << RegName(getRegList().List3To) << ",";
415*349cc55cSDimitry Andric       OS << RegName(getRegList().List4From) << "-"
416*349cc55cSDimitry Andric          << RegName(getRegList().List4To);
417fe6060f1SDimitry Andric       break;
418fe6060f1SDimitry Andric     case Token:
419fe6060f1SDimitry Andric       OS << "'" << getToken() << "'";
420fe6060f1SDimitry Andric       break;
421fe6060f1SDimitry Andric     }
422fe6060f1SDimitry Andric   }
423fe6060f1SDimitry Andric 
424fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createToken(StringRef Str, SMLoc S) {
425fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Token);
426fe6060f1SDimitry Andric     Op->Tok = Str;
427fe6060f1SDimitry Andric     Op->StartLoc = S;
428fe6060f1SDimitry Andric     Op->EndLoc = S;
429fe6060f1SDimitry Andric     return Op;
430fe6060f1SDimitry Andric   }
431fe6060f1SDimitry Andric 
432fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createReg(unsigned RegNo, SMLoc S,
433fe6060f1SDimitry Andric                                                 SMLoc E) {
434fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Register);
435fe6060f1SDimitry Andric     Op->Reg.RegNum = RegNo;
436fe6060f1SDimitry Andric     Op->StartLoc = S;
437fe6060f1SDimitry Andric     Op->EndLoc = E;
438fe6060f1SDimitry Andric     return Op;
439fe6060f1SDimitry Andric   }
440fe6060f1SDimitry Andric 
441*349cc55cSDimitry Andric   static std::unique_ptr<CSKYOperand> createRegSeq(unsigned RegNoFrom,
442*349cc55cSDimitry Andric                                                    unsigned RegNoTo, SMLoc S) {
443*349cc55cSDimitry Andric     auto Op = std::make_unique<CSKYOperand>(RegisterSeq);
444*349cc55cSDimitry Andric     Op->RegSeq.RegNumFrom = RegNoFrom;
445*349cc55cSDimitry Andric     Op->RegSeq.RegNumTo = RegNoTo;
446*349cc55cSDimitry Andric     Op->StartLoc = S;
447*349cc55cSDimitry Andric     Op->EndLoc = S;
448*349cc55cSDimitry Andric     return Op;
449*349cc55cSDimitry Andric   }
450*349cc55cSDimitry Andric 
451*349cc55cSDimitry Andric   static std::unique_ptr<CSKYOperand>
452*349cc55cSDimitry Andric   createRegList(SmallVector<unsigned, 4> reglist, SMLoc S) {
453*349cc55cSDimitry Andric     auto Op = std::make_unique<CSKYOperand>(RegisterList);
454*349cc55cSDimitry Andric     Op->RegList.List1From = 0;
455*349cc55cSDimitry Andric     Op->RegList.List1To = 0;
456*349cc55cSDimitry Andric     Op->RegList.List2From = 0;
457*349cc55cSDimitry Andric     Op->RegList.List2To = 0;
458*349cc55cSDimitry Andric     Op->RegList.List3From = 0;
459*349cc55cSDimitry Andric     Op->RegList.List3To = 0;
460*349cc55cSDimitry Andric     Op->RegList.List4From = 0;
461*349cc55cSDimitry Andric     Op->RegList.List4To = 0;
462*349cc55cSDimitry Andric 
463*349cc55cSDimitry Andric     for (unsigned i = 0; i < reglist.size(); i += 2) {
464*349cc55cSDimitry Andric       if (Op->RegList.List1From == 0) {
465*349cc55cSDimitry Andric         Op->RegList.List1From = reglist[i];
466*349cc55cSDimitry Andric         Op->RegList.List1To = reglist[i + 1];
467*349cc55cSDimitry Andric       } else if (Op->RegList.List2From == 0) {
468*349cc55cSDimitry Andric         Op->RegList.List2From = reglist[i];
469*349cc55cSDimitry Andric         Op->RegList.List2To = reglist[i + 1];
470*349cc55cSDimitry Andric       } else if (Op->RegList.List3From == 0) {
471*349cc55cSDimitry Andric         Op->RegList.List3From = reglist[i];
472*349cc55cSDimitry Andric         Op->RegList.List3To = reglist[i + 1];
473*349cc55cSDimitry Andric       } else if (Op->RegList.List4From == 0) {
474*349cc55cSDimitry Andric         Op->RegList.List4From = reglist[i];
475*349cc55cSDimitry Andric         Op->RegList.List4To = reglist[i + 1];
476*349cc55cSDimitry Andric       } else {
477*349cc55cSDimitry Andric         assert(0);
478*349cc55cSDimitry Andric       }
479*349cc55cSDimitry Andric     }
480*349cc55cSDimitry Andric 
481*349cc55cSDimitry Andric     Op->StartLoc = S;
482*349cc55cSDimitry Andric     Op->EndLoc = S;
483*349cc55cSDimitry Andric     return Op;
484*349cc55cSDimitry Andric   }
485*349cc55cSDimitry Andric 
486fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S,
487fe6060f1SDimitry Andric                                                 SMLoc E) {
488fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Immediate);
489fe6060f1SDimitry Andric     Op->Imm.Val = Val;
490fe6060f1SDimitry Andric     Op->StartLoc = S;
491fe6060f1SDimitry Andric     Op->EndLoc = E;
492fe6060f1SDimitry Andric     return Op;
493fe6060f1SDimitry Andric   }
494fe6060f1SDimitry Andric 
495*349cc55cSDimitry Andric   static std::unique_ptr<CSKYOperand> createConstpoolOp(const MCExpr *Val,
496*349cc55cSDimitry Andric                                                         SMLoc S, SMLoc E) {
497*349cc55cSDimitry Andric     auto Op = std::make_unique<CSKYOperand>(CPOP);
498*349cc55cSDimitry Andric     Op->CPool.Val = Val;
499*349cc55cSDimitry Andric     Op->StartLoc = S;
500*349cc55cSDimitry Andric     Op->EndLoc = E;
501*349cc55cSDimitry Andric     return Op;
502*349cc55cSDimitry Andric   }
503*349cc55cSDimitry Andric 
504fe6060f1SDimitry Andric   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
505fe6060f1SDimitry Andric     assert(Expr && "Expr shouldn't be null!");
506fe6060f1SDimitry Andric     if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
507fe6060f1SDimitry Andric       Inst.addOperand(MCOperand::createImm(CE->getValue()));
508fe6060f1SDimitry Andric     else
509fe6060f1SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
510fe6060f1SDimitry Andric   }
511fe6060f1SDimitry Andric 
512fe6060f1SDimitry Andric   // Used by the TableGen Code.
513fe6060f1SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
514fe6060f1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
515fe6060f1SDimitry Andric     Inst.addOperand(MCOperand::createReg(getReg()));
516fe6060f1SDimitry Andric   }
517fe6060f1SDimitry Andric 
518fe6060f1SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
519fe6060f1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
520fe6060f1SDimitry Andric     addExpr(Inst, getImm());
521fe6060f1SDimitry Andric   }
522*349cc55cSDimitry Andric 
523*349cc55cSDimitry Andric   void addConstpoolOperands(MCInst &Inst, unsigned N) const {
524*349cc55cSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
525*349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createExpr(getConstpoolOp()));
526*349cc55cSDimitry Andric   }
527*349cc55cSDimitry Andric 
528*349cc55cSDimitry Andric   void addRegSeqOperands(MCInst &Inst, unsigned N) const {
529*349cc55cSDimitry Andric     assert(N == 2 && "Invalid number of operands!");
530*349cc55cSDimitry Andric     auto regSeq = getRegSeq();
531*349cc55cSDimitry Andric 
532*349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createReg(regSeq.first));
533*349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createReg(regSeq.second));
534*349cc55cSDimitry Andric   }
535*349cc55cSDimitry Andric 
536*349cc55cSDimitry Andric   static unsigned getListValue(unsigned ListFrom, unsigned ListTo) {
537*349cc55cSDimitry Andric     if (ListFrom == ListTo && ListFrom == CSKY::R15)
538*349cc55cSDimitry Andric       return (1 << 4);
539*349cc55cSDimitry Andric     else if (ListFrom == ListTo && ListFrom == CSKY::R28)
540*349cc55cSDimitry Andric       return (1 << 8);
541*349cc55cSDimitry Andric     else if (ListFrom == CSKY::R4)
542*349cc55cSDimitry Andric       return ListTo - ListFrom + 1;
543*349cc55cSDimitry Andric     else if (ListFrom == CSKY::R16)
544*349cc55cSDimitry Andric       return ((ListTo - ListFrom + 1) << 5);
545*349cc55cSDimitry Andric     else
546*349cc55cSDimitry Andric       return 0;
547*349cc55cSDimitry Andric   }
548*349cc55cSDimitry Andric 
549*349cc55cSDimitry Andric   void addRegListOperands(MCInst &Inst, unsigned N) const {
550*349cc55cSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
551*349cc55cSDimitry Andric     auto regList = getRegList();
552*349cc55cSDimitry Andric 
553*349cc55cSDimitry Andric     unsigned V = 0;
554*349cc55cSDimitry Andric 
555*349cc55cSDimitry Andric     unsigned T = getListValue(regList.List1From, regList.List1To);
556*349cc55cSDimitry Andric     if (T != 0)
557*349cc55cSDimitry Andric       V = V | T;
558*349cc55cSDimitry Andric 
559*349cc55cSDimitry Andric     T = getListValue(regList.List2From, regList.List2To);
560*349cc55cSDimitry Andric     if (T != 0)
561*349cc55cSDimitry Andric       V = V | T;
562*349cc55cSDimitry Andric 
563*349cc55cSDimitry Andric     T = getListValue(regList.List3From, regList.List3To);
564*349cc55cSDimitry Andric     if (T != 0)
565*349cc55cSDimitry Andric       V = V | T;
566*349cc55cSDimitry Andric 
567*349cc55cSDimitry Andric     T = getListValue(regList.List4From, regList.List4To);
568*349cc55cSDimitry Andric     if (T != 0)
569*349cc55cSDimitry Andric       V = V | T;
570*349cc55cSDimitry Andric 
571*349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createImm(V));
572*349cc55cSDimitry Andric   }
573*349cc55cSDimitry Andric 
574*349cc55cSDimitry Andric   bool isValidForTie(const CSKYOperand &Other) const {
575*349cc55cSDimitry Andric     if (Kind != Other.Kind)
576*349cc55cSDimitry Andric       return false;
577*349cc55cSDimitry Andric 
578*349cc55cSDimitry Andric     switch (Kind) {
579*349cc55cSDimitry Andric     default:
580*349cc55cSDimitry Andric       llvm_unreachable("Unexpected kind");
581*349cc55cSDimitry Andric       return false;
582*349cc55cSDimitry Andric     case Register:
583*349cc55cSDimitry Andric       return Reg.RegNum == Other.Reg.RegNum;
584*349cc55cSDimitry Andric     }
585*349cc55cSDimitry Andric   }
586fe6060f1SDimitry Andric };
587fe6060f1SDimitry Andric } // end anonymous namespace.
588fe6060f1SDimitry Andric 
589fe6060f1SDimitry Andric #define GET_REGISTER_MATCHER
590fe6060f1SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME
591fe6060f1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
592fe6060f1SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
593fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
594fe6060f1SDimitry Andric 
595fe6060f1SDimitry Andric static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
596fe6060f1SDimitry Andric                                           unsigned VariantID = 0);
597fe6060f1SDimitry Andric 
598fe6060f1SDimitry Andric bool CSKYAsmParser::generateImmOutOfRangeError(
599fe6060f1SDimitry Andric     OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
600fe6060f1SDimitry Andric     Twine Msg = "immediate must be an integer in the range") {
601fe6060f1SDimitry Andric   SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
602fe6060f1SDimitry Andric   return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
603fe6060f1SDimitry Andric }
604fe6060f1SDimitry Andric 
605fe6060f1SDimitry Andric bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
606fe6060f1SDimitry Andric                                             OperandVector &Operands,
607fe6060f1SDimitry Andric                                             MCStreamer &Out,
608fe6060f1SDimitry Andric                                             uint64_t &ErrorInfo,
609fe6060f1SDimitry Andric                                             bool MatchingInlineAsm) {
610fe6060f1SDimitry Andric   MCInst Inst;
611fe6060f1SDimitry Andric   FeatureBitset MissingFeatures;
612fe6060f1SDimitry Andric 
613fe6060f1SDimitry Andric   auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
614fe6060f1SDimitry Andric                                      MatchingInlineAsm);
615fe6060f1SDimitry Andric   switch (Result) {
616fe6060f1SDimitry Andric   default:
617fe6060f1SDimitry Andric     break;
618fe6060f1SDimitry Andric   case Match_Success:
619*349cc55cSDimitry Andric     return processInstruction(Inst, IDLoc, Operands, Out);
620fe6060f1SDimitry Andric   case Match_MissingFeature: {
621fe6060f1SDimitry Andric     assert(MissingFeatures.any() && "Unknown missing features!");
622fe6060f1SDimitry Andric     ListSeparator LS;
623fe6060f1SDimitry Andric     std::string Msg = "instruction requires the following: ";
624fe6060f1SDimitry Andric     for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
625fe6060f1SDimitry Andric       if (MissingFeatures[i]) {
626fe6060f1SDimitry Andric         Msg += LS;
627fe6060f1SDimitry Andric         Msg += getSubtargetFeatureName(i);
628fe6060f1SDimitry Andric       }
629fe6060f1SDimitry Andric     }
630fe6060f1SDimitry Andric     return Error(IDLoc, Msg);
631fe6060f1SDimitry Andric   }
632fe6060f1SDimitry Andric   case Match_MnemonicFail: {
633fe6060f1SDimitry Andric     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
634fe6060f1SDimitry Andric     std::string Suggestion =
635fe6060f1SDimitry Andric         CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS);
636fe6060f1SDimitry Andric     return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
637fe6060f1SDimitry Andric   }
638fe6060f1SDimitry Andric   case Match_InvalidTiedOperand:
639fe6060f1SDimitry Andric   case Match_InvalidOperand: {
640fe6060f1SDimitry Andric     SMLoc ErrorLoc = IDLoc;
641fe6060f1SDimitry Andric     if (ErrorInfo != ~0U) {
642fe6060f1SDimitry Andric       if (ErrorInfo >= Operands.size())
643fe6060f1SDimitry Andric         return Error(ErrorLoc, "too few operands for instruction");
644fe6060f1SDimitry Andric 
645fe6060f1SDimitry Andric       ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
646fe6060f1SDimitry Andric       if (ErrorLoc == SMLoc())
647fe6060f1SDimitry Andric         ErrorLoc = IDLoc;
648fe6060f1SDimitry Andric     }
649fe6060f1SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
650fe6060f1SDimitry Andric   }
651fe6060f1SDimitry Andric   }
652fe6060f1SDimitry Andric 
653fe6060f1SDimitry Andric   // Handle the case when the error message is of specific type
654fe6060f1SDimitry Andric   // other than the generic Match_InvalidOperand, and the
655fe6060f1SDimitry Andric   // corresponding operand is missing.
656fe6060f1SDimitry Andric   if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
657fe6060f1SDimitry Andric     SMLoc ErrorLoc = IDLoc;
658fe6060f1SDimitry Andric     if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
659fe6060f1SDimitry Andric       return Error(ErrorLoc, "too few operands for instruction");
660fe6060f1SDimitry Andric   }
661fe6060f1SDimitry Andric 
662fe6060f1SDimitry Andric   switch (Result) {
663fe6060f1SDimitry Andric   default:
664fe6060f1SDimitry Andric     break;
665*349cc55cSDimitry Andric   case Match_InvalidSImm8:
666*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 7),
667*349cc55cSDimitry Andric                                       (1 << 7) - 1);
668*349cc55cSDimitry Andric   case Match_InvalidOImm3:
669*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 3));
670*349cc55cSDimitry Andric   case Match_InvalidOImm4:
671*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 4));
672*349cc55cSDimitry Andric   case Match_InvalidOImm5:
673*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
674*349cc55cSDimitry Andric   case Match_InvalidOImm6:
675*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6));
676*349cc55cSDimitry Andric   case Match_InvalidOImm8:
677*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 8));
678fe6060f1SDimitry Andric   case Match_InvalidOImm12:
679fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12));
680fe6060f1SDimitry Andric   case Match_InvalidOImm16:
681fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16));
682*349cc55cSDimitry Andric   case Match_InvalidUImm1:
683*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
684fe6060f1SDimitry Andric   case Match_InvalidUImm2:
685fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
686*349cc55cSDimitry Andric   case Match_InvalidUImm3:
687*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
688*349cc55cSDimitry Andric   case Match_InvalidUImm4:
689*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
690fe6060f1SDimitry Andric   case Match_InvalidUImm5:
691fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
692*349cc55cSDimitry Andric   case Match_InvalidUImm6:
693*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
694*349cc55cSDimitry Andric   case Match_InvalidUImm7:
695*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
696*349cc55cSDimitry Andric   case Match_InvalidUImm8:
697*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
698fe6060f1SDimitry Andric   case Match_InvalidUImm12:
699fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
700*349cc55cSDimitry Andric   case Match_InvalidUImm16:
701*349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
702*349cc55cSDimitry Andric   case Match_InvalidUImm5Shift1:
703*349cc55cSDimitry Andric     return generateImmOutOfRangeError(
704*349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 5) - 2,
705*349cc55cSDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
706fe6060f1SDimitry Andric   case Match_InvalidUImm12Shift1:
707fe6060f1SDimitry Andric     return generateImmOutOfRangeError(
708fe6060f1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 12) - 2,
709fe6060f1SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
710*349cc55cSDimitry Andric   case Match_InvalidUImm5Shift2:
711*349cc55cSDimitry Andric     return generateImmOutOfRangeError(
712*349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 5) - 4,
713*349cc55cSDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
714*349cc55cSDimitry Andric   case Match_InvalidUImm7Shift1:
715*349cc55cSDimitry Andric     return generateImmOutOfRangeError(
716*349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 7) - 2,
717*349cc55cSDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
718*349cc55cSDimitry Andric   case Match_InvalidUImm7Shift2:
719*349cc55cSDimitry Andric     return generateImmOutOfRangeError(
720*349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 7) - 4,
721*349cc55cSDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
722*349cc55cSDimitry Andric   case Match_InvalidUImm8Shift2:
723*349cc55cSDimitry Andric     return generateImmOutOfRangeError(
724*349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 4,
725*349cc55cSDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
726*349cc55cSDimitry Andric   case Match_InvalidUImm8Shift3:
727*349cc55cSDimitry Andric     return generateImmOutOfRangeError(
728*349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 8,
729*349cc55cSDimitry Andric         "immediate must be a multiple of 8 bytes in the range");
730*349cc55cSDimitry Andric   case Match_InvalidUImm8Shift8:
731*349cc55cSDimitry Andric     return generateImmOutOfRangeError(
732*349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 256,
733*349cc55cSDimitry Andric         "immediate must be a multiple of 256 bytes in the range");
734fe6060f1SDimitry Andric   case Match_InvalidUImm12Shift2:
735fe6060f1SDimitry Andric     return generateImmOutOfRangeError(
736fe6060f1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 12) - 4,
737fe6060f1SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
738fe6060f1SDimitry Andric   case Match_InvalidCSKYSymbol: {
739fe6060f1SDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
740fe6060f1SDimitry Andric     return Error(ErrorLoc, "operand must be a symbol name");
741fe6060f1SDimitry Andric   }
742fe6060f1SDimitry Andric   case Match_InvalidConstpool: {
743fe6060f1SDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
744fe6060f1SDimitry Andric     return Error(ErrorLoc, "operand must be a constpool symbol name");
745fe6060f1SDimitry Andric   }
746*349cc55cSDimitry Andric   case Match_InvalidPSRFlag: {
747*349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
748*349cc55cSDimitry Andric     return Error(ErrorLoc, "psrset operand is not valid");
749*349cc55cSDimitry Andric   }
750*349cc55cSDimitry Andric   case Match_InvalidRegSeq: {
751*349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
752*349cc55cSDimitry Andric     return Error(ErrorLoc, "Register sequence is not valid");
753*349cc55cSDimitry Andric   }
754*349cc55cSDimitry Andric   case Match_InvalidRegOutOfRange: {
755*349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
756*349cc55cSDimitry Andric     return Error(ErrorLoc, "register is out of range");
757*349cc55cSDimitry Andric   }
758*349cc55cSDimitry Andric   case Match_InvalidSPOperand: {
759*349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
760*349cc55cSDimitry Andric     return Error(ErrorLoc, "operand must be sp register");
761*349cc55cSDimitry Andric   }
762*349cc55cSDimitry Andric   case Match_RequiresSameSrcAndDst: {
763*349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
764*349cc55cSDimitry Andric     return Error(ErrorLoc, "src and dst operand must be same");
765*349cc55cSDimitry Andric   }
766*349cc55cSDimitry Andric   case Match_InvalidRegList: {
767*349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
768*349cc55cSDimitry Andric     return Error(ErrorLoc, "invalid register list");
769*349cc55cSDimitry Andric   }
770*349cc55cSDimitry Andric   }
771*349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "Result = " << Result);
772*349cc55cSDimitry Andric   llvm_unreachable("Unknown match type detected!");
773fe6060f1SDimitry Andric }
774fe6060f1SDimitry Andric 
775*349cc55cSDimitry Andric bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
776*349cc55cSDimitry Andric                                        OperandVector &Operands,
777*349cc55cSDimitry Andric                                        MCStreamer &Out) {
778*349cc55cSDimitry Andric 
779*349cc55cSDimitry Andric   if (Inst.getOpcode() == CSKY::LDQ32 || Inst.getOpcode() == CSKY::STQ32) {
780*349cc55cSDimitry Andric     if (Inst.getOperand(1).getReg() != CSKY::R4 ||
781*349cc55cSDimitry Andric         Inst.getOperand(2).getReg() != CSKY::R7) {
782*349cc55cSDimitry Andric       return Error(IDLoc, "Register sequence is not valid. 'r4-r7' expected");
783*349cc55cSDimitry Andric     }
784*349cc55cSDimitry Andric     Inst.setOpcode(Inst.getOpcode() == CSKY::LDQ32 ? CSKY::LDM32 : CSKY::STM32);
785*349cc55cSDimitry Andric     Out.emitInstruction(Inst, getSTI());
786*349cc55cSDimitry Andric     return false;
787*349cc55cSDimitry Andric   } else if (Inst.getOpcode() == CSKY::SEXT32 ||
788*349cc55cSDimitry Andric              Inst.getOpcode() == CSKY::ZEXT32) {
789*349cc55cSDimitry Andric     if (Inst.getOperand(2).getImm() < Inst.getOperand(3).getImm())
790*349cc55cSDimitry Andric       return Error(IDLoc, "msb must be greater or equal to lsb");
791*349cc55cSDimitry Andric   } else if (Inst.getOpcode() == CSKY::INS32) {
792*349cc55cSDimitry Andric     if (Inst.getOperand(3).getImm() < Inst.getOperand(4).getImm())
793*349cc55cSDimitry Andric       return Error(IDLoc, "msb must be greater or equal to lsb");
794*349cc55cSDimitry Andric   } else if (Inst.getOpcode() == CSKY::IDLY32) {
795*349cc55cSDimitry Andric     if (Inst.getOperand(0).getImm() > 32 || Inst.getOperand(0).getImm() < 0)
796*349cc55cSDimitry Andric       return Error(IDLoc, "n must be in range [0,32]");
797*349cc55cSDimitry Andric   }
798*349cc55cSDimitry Andric 
799*349cc55cSDimitry Andric   Out.emitInstruction(Inst, getSTI());
800*349cc55cSDimitry Andric   return false;
801fe6060f1SDimitry Andric }
802fe6060f1SDimitry Andric 
803fe6060f1SDimitry Andric // Attempts to match Name as a register (either using the default name or
804fe6060f1SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon
805fe6060f1SDimitry Andric // failure, returns true and sets RegNo to 0.
806*349cc55cSDimitry Andric static bool matchRegisterNameHelper(const MCSubtargetInfo &STI,
807*349cc55cSDimitry Andric                                     MCRegister &RegNo, StringRef Name) {
808fe6060f1SDimitry Andric   RegNo = MatchRegisterName(Name);
809fe6060f1SDimitry Andric 
810fe6060f1SDimitry Andric   if (RegNo == CSKY::NoRegister)
811fe6060f1SDimitry Andric     RegNo = MatchRegisterAltName(Name);
812fe6060f1SDimitry Andric 
813fe6060f1SDimitry Andric   return RegNo == CSKY::NoRegister;
814fe6060f1SDimitry Andric }
815fe6060f1SDimitry Andric 
816fe6060f1SDimitry Andric bool CSKYAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
817fe6060f1SDimitry Andric                                   SMLoc &EndLoc) {
818fe6060f1SDimitry Andric   const AsmToken &Tok = getParser().getTok();
819fe6060f1SDimitry Andric   StartLoc = Tok.getLoc();
820fe6060f1SDimitry Andric   EndLoc = Tok.getEndLoc();
821fe6060f1SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
822fe6060f1SDimitry Andric 
823*349cc55cSDimitry Andric   if (!matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name)) {
824fe6060f1SDimitry Andric     getParser().Lex(); // Eat identifier token.
825fe6060f1SDimitry Andric     return false;
826fe6060f1SDimitry Andric   }
827fe6060f1SDimitry Andric 
828*349cc55cSDimitry Andric   return MatchOperand_NoMatch;
829fe6060f1SDimitry Andric }
830fe6060f1SDimitry Andric 
831fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegister(OperandVector &Operands) {
832fe6060f1SDimitry Andric   SMLoc S = getLoc();
833fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
834fe6060f1SDimitry Andric 
835fe6060f1SDimitry Andric   switch (getLexer().getKind()) {
836fe6060f1SDimitry Andric   default:
837fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
838fe6060f1SDimitry Andric   case AsmToken::Identifier: {
839fe6060f1SDimitry Andric     StringRef Name = getLexer().getTok().getIdentifier();
840fe6060f1SDimitry Andric     MCRegister RegNo;
841fe6060f1SDimitry Andric 
842*349cc55cSDimitry Andric     if (matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name))
843fe6060f1SDimitry Andric       return MatchOperand_NoMatch;
844fe6060f1SDimitry Andric 
845fe6060f1SDimitry Andric     getLexer().Lex();
846fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createReg(RegNo, S, E));
847fe6060f1SDimitry Andric 
848fe6060f1SDimitry Andric     return MatchOperand_Success;
849fe6060f1SDimitry Andric   }
850fe6060f1SDimitry Andric   }
851fe6060f1SDimitry Andric }
852fe6060f1SDimitry Andric 
853fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) {
854fe6060f1SDimitry Andric   assert(getLexer().is(AsmToken::LParen));
855fe6060f1SDimitry Andric 
856fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken("(", getLoc()));
857fe6060f1SDimitry Andric 
858fe6060f1SDimitry Andric   auto Tok = getParser().Lex(); // Eat '('
859fe6060f1SDimitry Andric 
860fe6060f1SDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success) {
861fe6060f1SDimitry Andric     getLexer().UnLex(Tok);
862fe6060f1SDimitry Andric     Operands.pop_back();
863*349cc55cSDimitry Andric     return MatchOperand_NoMatch;
864*349cc55cSDimitry Andric   }
865*349cc55cSDimitry Andric 
866*349cc55cSDimitry Andric   if (getLexer().is(AsmToken::RParen)) {
867*349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createToken(")", getLoc()));
868*349cc55cSDimitry Andric     getParser().Lex(); // Eat ')'
869*349cc55cSDimitry Andric     return MatchOperand_Success;
870fe6060f1SDimitry Andric   }
871fe6060f1SDimitry Andric 
872fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::Comma)) {
873fe6060f1SDimitry Andric     Error(getLoc(), "expected ','");
874fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
875fe6060f1SDimitry Andric   }
876fe6060f1SDimitry Andric 
877fe6060f1SDimitry Andric   getParser().Lex(); // Eat ','
878fe6060f1SDimitry Andric 
879fe6060f1SDimitry Andric   if (parseRegister(Operands) == MatchOperand_Success) {
880fe6060f1SDimitry Andric     if (getLexer().isNot(AsmToken::LessLess)) {
881fe6060f1SDimitry Andric       Error(getLoc(), "expected '<<'");
882fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
883fe6060f1SDimitry Andric     }
884fe6060f1SDimitry Andric 
885fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createToken("<<", getLoc()));
886fe6060f1SDimitry Andric 
887fe6060f1SDimitry Andric     getParser().Lex(); // Eat '<<'
888fe6060f1SDimitry Andric 
889fe6060f1SDimitry Andric     if (parseImmediate(Operands) != MatchOperand_Success) {
890fe6060f1SDimitry Andric       Error(getLoc(), "expected imm");
891fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
892fe6060f1SDimitry Andric     }
893fe6060f1SDimitry Andric 
894fe6060f1SDimitry Andric   } else if (parseImmediate(Operands) != MatchOperand_Success) {
895fe6060f1SDimitry Andric     Error(getLoc(), "expected imm");
896fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
897fe6060f1SDimitry Andric   }
898fe6060f1SDimitry Andric 
899fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::RParen)) {
900fe6060f1SDimitry Andric     Error(getLoc(), "expected ')'");
901fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
902fe6060f1SDimitry Andric   }
903fe6060f1SDimitry Andric 
904fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken(")", getLoc()));
905fe6060f1SDimitry Andric 
906fe6060f1SDimitry Andric   getParser().Lex(); // Eat ')'
907fe6060f1SDimitry Andric 
908fe6060f1SDimitry Andric   return MatchOperand_Success;
909fe6060f1SDimitry Andric }
910fe6060f1SDimitry Andric 
911fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
912fe6060f1SDimitry Andric   switch (getLexer().getKind()) {
913fe6060f1SDimitry Andric   default:
914fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
915fe6060f1SDimitry Andric   case AsmToken::LParen:
916fe6060f1SDimitry Andric   case AsmToken::Minus:
917fe6060f1SDimitry Andric   case AsmToken::Plus:
918fe6060f1SDimitry Andric   case AsmToken::Integer:
919fe6060f1SDimitry Andric   case AsmToken::String:
920fe6060f1SDimitry Andric     break;
921fe6060f1SDimitry Andric   }
922fe6060f1SDimitry Andric 
923fe6060f1SDimitry Andric   const MCExpr *IdVal;
924fe6060f1SDimitry Andric   SMLoc S = getLoc();
925*349cc55cSDimitry Andric   if (getParser().parseExpression(IdVal)) {
926*349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
927fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
928*349cc55cSDimitry Andric   }
929fe6060f1SDimitry Andric 
930fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
931fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createImm(IdVal, S, E));
932fe6060f1SDimitry Andric   return MatchOperand_Success;
933fe6060f1SDimitry Andric }
934fe6060f1SDimitry Andric 
935fe6060f1SDimitry Andric /// Looks at a token type and creates the relevant operand from this
936fe6060f1SDimitry Andric /// information, adding to Operands. If operand was parsed, returns false, else
937fe6060f1SDimitry Andric /// true.
938fe6060f1SDimitry Andric bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
939fe6060f1SDimitry Andric   // Check if the current operand has a custom associated parser, if so, try to
940fe6060f1SDimitry Andric   // custom parse the operand, or fallback to the general approach.
941fe6060f1SDimitry Andric   OperandMatchResultTy Result =
942fe6060f1SDimitry Andric       MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
943fe6060f1SDimitry Andric   if (Result == MatchOperand_Success)
944fe6060f1SDimitry Andric     return false;
945fe6060f1SDimitry Andric   if (Result == MatchOperand_ParseFail)
946fe6060f1SDimitry Andric     return true;
947fe6060f1SDimitry Andric 
948fe6060f1SDimitry Andric   // Attempt to parse token as register
949*349cc55cSDimitry Andric   auto Res = parseRegister(Operands);
950*349cc55cSDimitry Andric   if (Res == MatchOperand_Success)
951fe6060f1SDimitry Andric     return false;
952*349cc55cSDimitry Andric   else if (Res == MatchOperand_ParseFail)
953*349cc55cSDimitry Andric     return true;
954fe6060f1SDimitry Andric 
955fe6060f1SDimitry Andric   // Attempt to parse token as (register, imm)
956*349cc55cSDimitry Andric   if (getLexer().is(AsmToken::LParen)) {
957*349cc55cSDimitry Andric     Res = parseBaseRegImm(Operands);
958*349cc55cSDimitry Andric     if (Res == MatchOperand_Success)
959fe6060f1SDimitry Andric       return false;
960*349cc55cSDimitry Andric     else if (Res == MatchOperand_ParseFail)
961*349cc55cSDimitry Andric       return true;
962*349cc55cSDimitry Andric   }
963fe6060f1SDimitry Andric 
964*349cc55cSDimitry Andric   Res = parseImmediate(Operands);
965*349cc55cSDimitry Andric   if (Res == MatchOperand_Success)
966fe6060f1SDimitry Andric     return false;
967*349cc55cSDimitry Andric   else if (Res == MatchOperand_ParseFail)
968*349cc55cSDimitry Andric     return true;
969fe6060f1SDimitry Andric 
970fe6060f1SDimitry Andric   // Finally we have exhausted all options and must declare defeat.
971fe6060f1SDimitry Andric   Error(getLoc(), "unknown operand");
972fe6060f1SDimitry Andric   return true;
973fe6060f1SDimitry Andric }
974fe6060f1SDimitry Andric 
975fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
976fe6060f1SDimitry Andric   SMLoc S = getLoc();
977fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
978*349cc55cSDimitry Andric   const MCExpr *Res;
979fe6060f1SDimitry Andric 
980fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
981fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
982fe6060f1SDimitry Andric 
983fe6060f1SDimitry Andric   StringRef Identifier;
984*349cc55cSDimitry Andric   AsmToken Tok = getLexer().getTok();
985*349cc55cSDimitry Andric 
986*349cc55cSDimitry Andric   if (getParser().parseIdentifier(Identifier)) {
987*349cc55cSDimitry Andric     Error(getLoc(), "unknown identifier");
988fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
989*349cc55cSDimitry Andric   }
990fe6060f1SDimitry Andric 
991fe6060f1SDimitry Andric   CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
992fe6060f1SDimitry Andric   if (Identifier.consume_back("@GOT"))
993fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOT;
994fe6060f1SDimitry Andric   else if (Identifier.consume_back("@GOTOFF"))
995fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOTOFF;
996fe6060f1SDimitry Andric   else if (Identifier.consume_back("@PLT"))
997fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_PLT;
998fe6060f1SDimitry Andric   else if (Identifier.consume_back("@GOTPC"))
999fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOTPC;
1000*349cc55cSDimitry Andric   else if (Identifier.consume_back("@TLSGD32"))
1001*349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSGD;
1002*349cc55cSDimitry Andric   else if (Identifier.consume_back("@GOTTPOFF"))
1003*349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSIE;
1004*349cc55cSDimitry Andric   else if (Identifier.consume_back("@TPOFF"))
1005*349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSLE;
1006*349cc55cSDimitry Andric   else if (Identifier.consume_back("@TLSLDM32"))
1007*349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSLDM;
1008*349cc55cSDimitry Andric   else if (Identifier.consume_back("@TLSLDO32"))
1009*349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSLDO;
1010fe6060f1SDimitry Andric 
1011*349cc55cSDimitry Andric   MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1012fe6060f1SDimitry Andric 
1013*349cc55cSDimitry Andric   if (!Sym)
1014*349cc55cSDimitry Andric     Sym = getContext().getOrCreateSymbol(Identifier);
1015*349cc55cSDimitry Andric 
1016*349cc55cSDimitry Andric   if (Sym->isVariable()) {
1017*349cc55cSDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1018*349cc55cSDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
1019*349cc55cSDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1020*349cc55cSDimitry Andric       Error(getLoc(), "unknown symbol");
1021*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1022*349cc55cSDimitry Andric     }
1023*349cc55cSDimitry Andric     Res = V;
1024*349cc55cSDimitry Andric   } else
1025*349cc55cSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1026*349cc55cSDimitry Andric 
1027*349cc55cSDimitry Andric   MCBinaryExpr::Opcode Opcode;
1028*349cc55cSDimitry Andric   switch (getLexer().getKind()) {
1029*349cc55cSDimitry Andric   default:
1030fe6060f1SDimitry Andric     if (Kind != CSKYMCExpr::VK_CSKY_None)
1031fe6060f1SDimitry Andric       Res = CSKYMCExpr::create(Res, Kind, getContext());
1032fe6060f1SDimitry Andric 
1033fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createImm(Res, S, E));
1034fe6060f1SDimitry Andric     return MatchOperand_Success;
1035*349cc55cSDimitry Andric   case AsmToken::Plus:
1036*349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Add;
1037*349cc55cSDimitry Andric     break;
1038*349cc55cSDimitry Andric   case AsmToken::Minus:
1039*349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Sub;
1040*349cc55cSDimitry Andric     break;
1041*349cc55cSDimitry Andric   }
1042*349cc55cSDimitry Andric 
1043*349cc55cSDimitry Andric   getLexer().Lex(); // eat + or -
1044*349cc55cSDimitry Andric 
1045*349cc55cSDimitry Andric   const MCExpr *Expr;
1046*349cc55cSDimitry Andric   if (getParser().parseExpression(Expr)) {
1047*349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1048*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1049*349cc55cSDimitry Andric   }
1050*349cc55cSDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1051*349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createImm(Res, S, E));
1052*349cc55cSDimitry Andric   return MatchOperand_Success;
1053*349cc55cSDimitry Andric }
1054*349cc55cSDimitry Andric 
1055*349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parseDataSymbol(OperandVector &Operands) {
1056*349cc55cSDimitry Andric   SMLoc S = getLoc();
1057*349cc55cSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1058*349cc55cSDimitry Andric   const MCExpr *Res;
1059*349cc55cSDimitry Andric 
1060*349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::LBrac)
1061*349cc55cSDimitry Andric     return MatchOperand_NoMatch;
1062*349cc55cSDimitry Andric 
1063*349cc55cSDimitry Andric   getLexer().Lex(); // Eat '['.
1064*349cc55cSDimitry Andric 
1065*349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier) {
1066*349cc55cSDimitry Andric     const MCExpr *Expr;
1067*349cc55cSDimitry Andric     if (getParser().parseExpression(Expr)) {
1068*349cc55cSDimitry Andric       Error(getLoc(), "unknown expression");
1069*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1070*349cc55cSDimitry Andric     }
1071*349cc55cSDimitry Andric 
1072*349cc55cSDimitry Andric     if (getLexer().getKind() != AsmToken::RBrac) {
1073*349cc55cSDimitry Andric       Error(getLoc(), "expected ]");
1074*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1075*349cc55cSDimitry Andric     }
1076*349cc55cSDimitry Andric 
1077*349cc55cSDimitry Andric     getLexer().Lex(); // Eat ']'.
1078*349cc55cSDimitry Andric 
1079*349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1080*349cc55cSDimitry Andric     return MatchOperand_Success;
1081*349cc55cSDimitry Andric   }
1082*349cc55cSDimitry Andric 
1083*349cc55cSDimitry Andric   AsmToken Tok = getLexer().getTok();
1084*349cc55cSDimitry Andric   StringRef Identifier;
1085*349cc55cSDimitry Andric 
1086*349cc55cSDimitry Andric   if (getParser().parseIdentifier(Identifier)) {
1087*349cc55cSDimitry Andric     Error(getLoc(), "unknown identifier " + Identifier);
1088*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1089*349cc55cSDimitry Andric   }
1090*349cc55cSDimitry Andric 
1091*349cc55cSDimitry Andric   CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
1092*349cc55cSDimitry Andric   if (Identifier.consume_back("@GOT"))
1093*349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4;
1094*349cc55cSDimitry Andric   else if (Identifier.consume_back("@PLT"))
1095*349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4;
1096*349cc55cSDimitry Andric 
1097*349cc55cSDimitry Andric   MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1098*349cc55cSDimitry Andric 
1099*349cc55cSDimitry Andric   if (!Sym)
1100*349cc55cSDimitry Andric     Sym = getContext().getOrCreateSymbol(Identifier);
1101*349cc55cSDimitry Andric 
1102*349cc55cSDimitry Andric   if (Sym->isVariable()) {
1103*349cc55cSDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1104*349cc55cSDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
1105*349cc55cSDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1106*349cc55cSDimitry Andric       Error(getLoc(), "unknown symbol");
1107*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1108*349cc55cSDimitry Andric     }
1109*349cc55cSDimitry Andric     Res = V;
1110*349cc55cSDimitry Andric   } else {
1111*349cc55cSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1112*349cc55cSDimitry Andric   }
1113*349cc55cSDimitry Andric 
1114*349cc55cSDimitry Andric   MCBinaryExpr::Opcode Opcode;
1115*349cc55cSDimitry Andric   switch (getLexer().getKind()) {
1116*349cc55cSDimitry Andric   default:
1117*349cc55cSDimitry Andric     Error(getLoc(), "unknown symbol");
1118*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1119*349cc55cSDimitry Andric   case AsmToken::RBrac:
1120*349cc55cSDimitry Andric 
1121*349cc55cSDimitry Andric     getLexer().Lex(); // Eat ']'.
1122*349cc55cSDimitry Andric 
1123*349cc55cSDimitry Andric     if (Kind != CSKYMCExpr::VK_CSKY_None)
1124*349cc55cSDimitry Andric       Res = CSKYMCExpr::create(Res, Kind, getContext());
1125*349cc55cSDimitry Andric 
1126*349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1127*349cc55cSDimitry Andric     return MatchOperand_Success;
1128*349cc55cSDimitry Andric   case AsmToken::Plus:
1129*349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Add;
1130*349cc55cSDimitry Andric     break;
1131*349cc55cSDimitry Andric   case AsmToken::Minus:
1132*349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Sub;
1133*349cc55cSDimitry Andric     break;
1134*349cc55cSDimitry Andric   }
1135*349cc55cSDimitry Andric 
1136*349cc55cSDimitry Andric   getLexer().Lex(); // eat + or -
1137*349cc55cSDimitry Andric 
1138*349cc55cSDimitry Andric   const MCExpr *Expr;
1139*349cc55cSDimitry Andric   if (getParser().parseExpression(Expr)) {
1140*349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1141*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1142*349cc55cSDimitry Andric   }
1143*349cc55cSDimitry Andric 
1144*349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::RBrac) {
1145*349cc55cSDimitry Andric     Error(getLoc(), "expected ']'");
1146*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1147*349cc55cSDimitry Andric   }
1148*349cc55cSDimitry Andric 
1149*349cc55cSDimitry Andric   getLexer().Lex(); // Eat ']'.
1150*349cc55cSDimitry Andric 
1151*349cc55cSDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1152*349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1153*349cc55cSDimitry Andric   return MatchOperand_Success;
1154fe6060f1SDimitry Andric }
1155fe6060f1SDimitry Andric 
1156fe6060f1SDimitry Andric OperandMatchResultTy
1157fe6060f1SDimitry Andric CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
1158fe6060f1SDimitry Andric   SMLoc S = getLoc();
1159fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1160*349cc55cSDimitry Andric   const MCExpr *Res;
1161fe6060f1SDimitry Andric 
1162fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::LBrac)
1163fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1164fe6060f1SDimitry Andric 
1165fe6060f1SDimitry Andric   getLexer().Lex(); // Eat '['.
1166fe6060f1SDimitry Andric 
1167*349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier) {
1168*349cc55cSDimitry Andric     const MCExpr *Expr;
1169*349cc55cSDimitry Andric     if (getParser().parseExpression(Expr)) {
1170*349cc55cSDimitry Andric       Error(getLoc(), "unknown expression");
1171fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
1172*349cc55cSDimitry Andric     }
1173fe6060f1SDimitry Andric 
1174*349cc55cSDimitry Andric     if (getLexer().getKind() != AsmToken::RBrac) {
1175*349cc55cSDimitry Andric       Error(getLoc(), "expected ']'");
1176*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1177*349cc55cSDimitry Andric     }
1178fe6060f1SDimitry Andric 
1179fe6060f1SDimitry Andric     getLexer().Lex(); // Eat ']'.
1180fe6060f1SDimitry Andric 
1181*349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1182*349cc55cSDimitry Andric     return MatchOperand_Success;
1183*349cc55cSDimitry Andric   }
1184*349cc55cSDimitry Andric 
1185*349cc55cSDimitry Andric   AsmToken Tok = getLexer().getTok();
1186*349cc55cSDimitry Andric   StringRef Identifier;
1187*349cc55cSDimitry Andric 
1188*349cc55cSDimitry Andric   if (getParser().parseIdentifier(Identifier)) {
1189*349cc55cSDimitry Andric     Error(getLoc(), "unknown identifier");
1190*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1191*349cc55cSDimitry Andric   }
1192*349cc55cSDimitry Andric 
1193*349cc55cSDimitry Andric   MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1194*349cc55cSDimitry Andric 
1195*349cc55cSDimitry Andric   if (!Sym)
1196*349cc55cSDimitry Andric     Sym = getContext().getOrCreateSymbol(Identifier);
1197*349cc55cSDimitry Andric 
1198*349cc55cSDimitry Andric   if (Sym->isVariable()) {
1199*349cc55cSDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1200*349cc55cSDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
1201*349cc55cSDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1202*349cc55cSDimitry Andric       Error(getLoc(), "unknown symbol");
1203*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1204*349cc55cSDimitry Andric     }
1205*349cc55cSDimitry Andric     Res = V;
1206*349cc55cSDimitry Andric   } else {
1207*349cc55cSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1208*349cc55cSDimitry Andric   }
1209*349cc55cSDimitry Andric 
1210*349cc55cSDimitry Andric   MCBinaryExpr::Opcode Opcode;
1211*349cc55cSDimitry Andric   switch (getLexer().getKind()) {
1212*349cc55cSDimitry Andric   default:
1213*349cc55cSDimitry Andric     Error(getLoc(), "unknown symbol");
1214*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1215*349cc55cSDimitry Andric   case AsmToken::RBrac:
1216*349cc55cSDimitry Andric 
1217*349cc55cSDimitry Andric     getLexer().Lex(); // Eat ']'.
1218*349cc55cSDimitry Andric 
1219*349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1220*349cc55cSDimitry Andric     return MatchOperand_Success;
1221*349cc55cSDimitry Andric   case AsmToken::Plus:
1222*349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Add;
1223*349cc55cSDimitry Andric     break;
1224*349cc55cSDimitry Andric   case AsmToken::Minus:
1225*349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Sub;
1226*349cc55cSDimitry Andric     break;
1227*349cc55cSDimitry Andric   }
1228*349cc55cSDimitry Andric 
1229*349cc55cSDimitry Andric   getLexer().Lex(); // eat + or -
1230*349cc55cSDimitry Andric 
1231*349cc55cSDimitry Andric   const MCExpr *Expr;
1232*349cc55cSDimitry Andric   if (getParser().parseExpression(Expr)) {
1233*349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1234*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1235*349cc55cSDimitry Andric   }
1236*349cc55cSDimitry Andric 
1237*349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::RBrac) {
1238*349cc55cSDimitry Andric     Error(getLoc(), "expected ']'");
1239*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1240*349cc55cSDimitry Andric   }
1241*349cc55cSDimitry Andric 
1242*349cc55cSDimitry Andric   getLexer().Lex(); // Eat ']'.
1243*349cc55cSDimitry Andric 
1244*349cc55cSDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1245*349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1246*349cc55cSDimitry Andric   return MatchOperand_Success;
1247*349cc55cSDimitry Andric }
1248*349cc55cSDimitry Andric 
1249*349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parsePSRFlag(OperandVector &Operands) {
1250*349cc55cSDimitry Andric   SMLoc S = getLoc();
1251*349cc55cSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1252*349cc55cSDimitry Andric 
1253*349cc55cSDimitry Andric   unsigned Flag = 0;
1254*349cc55cSDimitry Andric 
1255*349cc55cSDimitry Andric   while (getLexer().isNot(AsmToken::EndOfStatement)) {
1256*349cc55cSDimitry Andric     StringRef Identifier;
1257*349cc55cSDimitry Andric     if (getParser().parseIdentifier(Identifier)) {
1258*349cc55cSDimitry Andric       Error(getLoc(), "unknown identifier " + Identifier);
1259*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1260*349cc55cSDimitry Andric     }
1261*349cc55cSDimitry Andric 
1262*349cc55cSDimitry Andric     if (Identifier == "sie")
1263*349cc55cSDimitry Andric       Flag = (1 << 4) | Flag;
1264*349cc55cSDimitry Andric     else if (Identifier == "ee")
1265*349cc55cSDimitry Andric       Flag = (1 << 3) | Flag;
1266*349cc55cSDimitry Andric     else if (Identifier == "ie")
1267*349cc55cSDimitry Andric       Flag = (1 << 2) | Flag;
1268*349cc55cSDimitry Andric     else if (Identifier == "fe")
1269*349cc55cSDimitry Andric       Flag = (1 << 1) | Flag;
1270*349cc55cSDimitry Andric     else if (Identifier == "af")
1271*349cc55cSDimitry Andric       Flag = (1 << 0) | Flag;
1272*349cc55cSDimitry Andric     else {
1273*349cc55cSDimitry Andric       Error(getLoc(), "expected " + Identifier);
1274*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1275*349cc55cSDimitry Andric     }
1276*349cc55cSDimitry Andric 
1277*349cc55cSDimitry Andric     if (getLexer().is(AsmToken::EndOfStatement))
1278*349cc55cSDimitry Andric       break;
1279*349cc55cSDimitry Andric 
1280*349cc55cSDimitry Andric     if (getLexer().is(AsmToken::Comma)) {
1281*349cc55cSDimitry Andric       getLexer().Lex(); // eat ','
1282*349cc55cSDimitry Andric     } else {
1283*349cc55cSDimitry Andric       Error(getLoc(), "expected ,");
1284*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1285*349cc55cSDimitry Andric     }
1286*349cc55cSDimitry Andric   }
1287*349cc55cSDimitry Andric 
1288*349cc55cSDimitry Andric   Operands.push_back(
1289*349cc55cSDimitry Andric       CSKYOperand::createImm(MCConstantExpr::create(Flag, getContext()), S, E));
1290*349cc55cSDimitry Andric   return MatchOperand_Success;
1291*349cc55cSDimitry Andric }
1292*349cc55cSDimitry Andric 
1293*349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegSeq(OperandVector &Operands) {
1294*349cc55cSDimitry Andric   SMLoc S = getLoc();
1295*349cc55cSDimitry Andric 
1296*349cc55cSDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success)
1297*349cc55cSDimitry Andric     return MatchOperand_NoMatch;
1298*349cc55cSDimitry Andric 
1299*349cc55cSDimitry Andric   auto Ry = Operands.back()->getReg();
1300*349cc55cSDimitry Andric   Operands.pop_back();
1301*349cc55cSDimitry Andric 
1302*349cc55cSDimitry Andric   if (getLexer().isNot(AsmToken::Minus)) {
1303*349cc55cSDimitry Andric     Error(getLoc(), "expected '-'");
1304*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1305*349cc55cSDimitry Andric   }
1306*349cc55cSDimitry Andric 
1307*349cc55cSDimitry Andric   getLexer().Lex(); // eat '-'
1308*349cc55cSDimitry Andric 
1309*349cc55cSDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success) {
1310*349cc55cSDimitry Andric     Error(getLoc(), "invalid register");
1311*349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1312*349cc55cSDimitry Andric   }
1313*349cc55cSDimitry Andric 
1314*349cc55cSDimitry Andric   auto Rz = Operands.back()->getReg();
1315*349cc55cSDimitry Andric   Operands.pop_back();
1316*349cc55cSDimitry Andric 
1317*349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createRegSeq(Ry, Rz, S));
1318*349cc55cSDimitry Andric   return MatchOperand_Success;
1319*349cc55cSDimitry Andric }
1320*349cc55cSDimitry Andric 
1321*349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegList(OperandVector &Operands) {
1322*349cc55cSDimitry Andric   SMLoc S = getLoc();
1323*349cc55cSDimitry Andric 
1324*349cc55cSDimitry Andric   SmallVector<unsigned, 4> reglist;
1325*349cc55cSDimitry Andric 
1326*349cc55cSDimitry Andric   while (true) {
1327*349cc55cSDimitry Andric 
1328*349cc55cSDimitry Andric     if (parseRegister(Operands) != MatchOperand_Success) {
1329*349cc55cSDimitry Andric       Error(getLoc(), "invalid register");
1330*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1331*349cc55cSDimitry Andric     }
1332*349cc55cSDimitry Andric 
1333*349cc55cSDimitry Andric     auto Ry = Operands.back()->getReg();
1334*349cc55cSDimitry Andric     Operands.pop_back();
1335*349cc55cSDimitry Andric 
1336*349cc55cSDimitry Andric     if (getLexer().is(AsmToken::Minus)) {
1337*349cc55cSDimitry Andric       getLexer().Lex(); // eat '-'
1338*349cc55cSDimitry Andric 
1339*349cc55cSDimitry Andric       if (parseRegister(Operands) != MatchOperand_Success) {
1340*349cc55cSDimitry Andric         Error(getLoc(), "invalid register");
1341*349cc55cSDimitry Andric         return MatchOperand_ParseFail;
1342*349cc55cSDimitry Andric       }
1343*349cc55cSDimitry Andric 
1344*349cc55cSDimitry Andric       auto Rz = Operands.back()->getReg();
1345*349cc55cSDimitry Andric       Operands.pop_back();
1346*349cc55cSDimitry Andric 
1347*349cc55cSDimitry Andric       reglist.push_back(Ry);
1348*349cc55cSDimitry Andric       reglist.push_back(Rz);
1349*349cc55cSDimitry Andric 
1350*349cc55cSDimitry Andric       if (getLexer().is(AsmToken::Comma))
1351*349cc55cSDimitry Andric         getLexer().Lex(); // eat ','
1352*349cc55cSDimitry Andric       else if (getLexer().is(AsmToken::EndOfStatement))
1353*349cc55cSDimitry Andric         break;
1354*349cc55cSDimitry Andric 
1355*349cc55cSDimitry Andric     } else if (getLexer().is(AsmToken::Comma)) {
1356*349cc55cSDimitry Andric       reglist.push_back(Ry);
1357*349cc55cSDimitry Andric       reglist.push_back(Ry);
1358*349cc55cSDimitry Andric 
1359*349cc55cSDimitry Andric       getLexer().Lex(); // eat ','
1360*349cc55cSDimitry Andric     } else if (getLexer().is(AsmToken::EndOfStatement)) {
1361*349cc55cSDimitry Andric       reglist.push_back(Ry);
1362*349cc55cSDimitry Andric       reglist.push_back(Ry);
1363*349cc55cSDimitry Andric       break;
1364*349cc55cSDimitry Andric     } else {
1365*349cc55cSDimitry Andric       Error(getLoc(), "invalid register list");
1366*349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1367*349cc55cSDimitry Andric     }
1368*349cc55cSDimitry Andric   }
1369*349cc55cSDimitry Andric 
1370*349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createRegList(reglist, S));
1371fe6060f1SDimitry Andric   return MatchOperand_Success;
1372fe6060f1SDimitry Andric }
1373fe6060f1SDimitry Andric 
1374fe6060f1SDimitry Andric bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1375fe6060f1SDimitry Andric                                      SMLoc NameLoc, OperandVector &Operands) {
1376fe6060f1SDimitry Andric   // First operand is token for instruction.
1377fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken(Name, NameLoc));
1378fe6060f1SDimitry Andric 
1379fe6060f1SDimitry Andric   // If there are no more operands, then finish.
1380fe6060f1SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement))
1381fe6060f1SDimitry Andric     return false;
1382fe6060f1SDimitry Andric 
1383fe6060f1SDimitry Andric   // Parse first operand.
1384fe6060f1SDimitry Andric   if (parseOperand(Operands, Name))
1385fe6060f1SDimitry Andric     return true;
1386fe6060f1SDimitry Andric 
1387fe6060f1SDimitry Andric   // Parse until end of statement, consuming commas between operands.
1388fe6060f1SDimitry Andric   while (getLexer().is(AsmToken::Comma)) {
1389fe6060f1SDimitry Andric     // Consume comma token.
1390fe6060f1SDimitry Andric     getLexer().Lex();
1391fe6060f1SDimitry Andric 
1392fe6060f1SDimitry Andric     // Parse next operand.
1393fe6060f1SDimitry Andric     if (parseOperand(Operands, Name))
1394fe6060f1SDimitry Andric       return true;
1395fe6060f1SDimitry Andric   }
1396fe6060f1SDimitry Andric 
1397fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1398fe6060f1SDimitry Andric     SMLoc Loc = getLexer().getLoc();
1399fe6060f1SDimitry Andric     getParser().eatToEndOfStatement();
1400fe6060f1SDimitry Andric     return Error(Loc, "unexpected token");
1401fe6060f1SDimitry Andric   }
1402fe6060f1SDimitry Andric 
1403fe6060f1SDimitry Andric   getParser().Lex(); // Consume the EndOfStatement.
1404fe6060f1SDimitry Andric   return false;
1405fe6060f1SDimitry Andric }
1406fe6060f1SDimitry Andric 
1407fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::tryParseRegister(unsigned &RegNo,
1408fe6060f1SDimitry Andric                                                      SMLoc &StartLoc,
1409fe6060f1SDimitry Andric                                                      SMLoc &EndLoc) {
1410fe6060f1SDimitry Andric   const AsmToken &Tok = getParser().getTok();
1411fe6060f1SDimitry Andric   StartLoc = Tok.getLoc();
1412fe6060f1SDimitry Andric   EndLoc = Tok.getEndLoc();
1413fe6060f1SDimitry Andric 
1414fe6060f1SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
1415fe6060f1SDimitry Andric 
1416*349cc55cSDimitry Andric   if (matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name))
1417fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1418fe6060f1SDimitry Andric 
1419fe6060f1SDimitry Andric   getParser().Lex(); // Eat identifier token.
1420fe6060f1SDimitry Andric   return MatchOperand_Success;
1421fe6060f1SDimitry Andric }
1422fe6060f1SDimitry Andric 
1423fe6060f1SDimitry Andric bool CSKYAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
1424fe6060f1SDimitry Andric 
1425fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser() {
1426fe6060f1SDimitry Andric   RegisterMCAsmParser<CSKYAsmParser> X(getTheCSKYTarget());
1427fe6060f1SDimitry Andric }
1428