xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
1349cc55cSDimitry Andric //===---- CSKYAsmParser.cpp - Parse CSKY assembly to MCInst instructions --===//
2fe6060f1SDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric 
9349cc55cSDimitry 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"
140eae32dcSDimitry Andric #include "llvm/ADT/Statistic.h"
15fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
16fe6060f1SDimitry Andric #include "llvm/CodeGen/Register.h"
17fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h"
18fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h"
19fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h"
20fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
21fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
22fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
23fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
24349cc55cSDimitry Andric #include "llvm/MC/MCSectionELF.h"
25fe6060f1SDimitry Andric #include "llvm/MC/MCStreamer.h"
26fe6060f1SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
28fe6060f1SDimitry Andric #include "llvm/Support/Casting.h"
290eae32dcSDimitry Andric #include "llvm/Support/CommandLine.h"
30349cc55cSDimitry Andric #include "llvm/Support/Debug.h"
31349cc55cSDimitry Andric 
320eae32dcSDimitry Andric using namespace llvm;
330eae32dcSDimitry Andric 
34349cc55cSDimitry Andric #define DEBUG_TYPE "csky-asm-parser"
35fe6060f1SDimitry Andric 
360eae32dcSDimitry Andric // Include the auto-generated portion of the compress emitter.
370eae32dcSDimitry Andric #define GEN_COMPRESS_INSTR
380eae32dcSDimitry Andric #include "CSKYGenCompressInstEmitter.inc"
390eae32dcSDimitry Andric 
400eae32dcSDimitry Andric STATISTIC(CSKYNumInstrsCompressed,
410eae32dcSDimitry Andric           "Number of C-SKY Compressed instructions emitted");
420eae32dcSDimitry Andric 
430eae32dcSDimitry Andric static cl::opt<bool>
440eae32dcSDimitry Andric     EnableCompressedInst("enable-csky-asm-compressed-inst", cl::Hidden,
450eae32dcSDimitry Andric                          cl::init(false),
460eae32dcSDimitry Andric                          cl::desc("Enable C-SKY asm compressed instruction"));
47fe6060f1SDimitry Andric 
48fe6060f1SDimitry Andric namespace {
49fe6060f1SDimitry Andric struct CSKYOperand;
50fe6060f1SDimitry Andric 
51fe6060f1SDimitry Andric class CSKYAsmParser : public MCTargetAsmParser {
52fe6060f1SDimitry Andric 
53349cc55cSDimitry Andric   const MCRegisterInfo *MRI;
54349cc55cSDimitry Andric 
55fe6060f1SDimitry Andric   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
56fe6060f1SDimitry Andric                                   int64_t Lower, int64_t Upper, Twine Msg);
57fe6060f1SDimitry Andric 
58fe6060f1SDimitry Andric   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
59fe6060f1SDimitry Andric 
60fe6060f1SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
61fe6060f1SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
62fe6060f1SDimitry Andric                                uint64_t &ErrorInfo,
63fe6060f1SDimitry Andric                                bool MatchingInlineAsm) override;
64fe6060f1SDimitry Andric 
65fe6060f1SDimitry Andric   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
66fe6060f1SDimitry Andric 
67fe6060f1SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
68fe6060f1SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
69fe6060f1SDimitry Andric 
70fe6060f1SDimitry Andric   bool ParseDirective(AsmToken DirectiveID) override;
71fe6060f1SDimitry Andric 
720eae32dcSDimitry Andric   // Helper to actually emit an instruction to the MCStreamer. Also, when
730eae32dcSDimitry Andric   // possible, compression of the instruction is performed.
740eae32dcSDimitry Andric   void emitToStreamer(MCStreamer &S, const MCInst &Inst);
750eae32dcSDimitry Andric 
76fe6060f1SDimitry Andric   OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
77fe6060f1SDimitry Andric                                         SMLoc &EndLoc) override;
78fe6060f1SDimitry Andric 
79349cc55cSDimitry Andric   bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
80349cc55cSDimitry Andric                           MCStreamer &Out);
81349cc55cSDimitry Andric 
82fe6060f1SDimitry Andric // Auto-generated instruction matching functions
83fe6060f1SDimitry Andric #define GET_ASSEMBLER_HEADER
84fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
85fe6060f1SDimitry Andric 
86fe6060f1SDimitry Andric   OperandMatchResultTy parseImmediate(OperandVector &Operands);
87fe6060f1SDimitry Andric   OperandMatchResultTy parseRegister(OperandVector &Operands);
88fe6060f1SDimitry Andric   OperandMatchResultTy parseBaseRegImm(OperandVector &Operands);
89fe6060f1SDimitry Andric   OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands);
90fe6060f1SDimitry Andric   OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands);
91349cc55cSDimitry Andric   OperandMatchResultTy parseDataSymbol(OperandVector &Operands);
92349cc55cSDimitry Andric   OperandMatchResultTy parsePSRFlag(OperandVector &Operands);
93349cc55cSDimitry Andric   OperandMatchResultTy parseRegSeq(OperandVector &Operands);
94349cc55cSDimitry Andric   OperandMatchResultTy parseRegList(OperandVector &Operands);
95fe6060f1SDimitry Andric 
96fe6060f1SDimitry Andric   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
97fe6060f1SDimitry Andric 
98fe6060f1SDimitry Andric public:
99fe6060f1SDimitry Andric   enum CSKYMatchResultTy {
100fe6060f1SDimitry Andric     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
101349cc55cSDimitry Andric     Match_RequiresSameSrcAndDst,
102349cc55cSDimitry Andric     Match_InvalidRegOutOfRange,
103fe6060f1SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
104fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
105fe6060f1SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES
106fe6060f1SDimitry Andric   };
107fe6060f1SDimitry Andric 
108fe6060f1SDimitry Andric   CSKYAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
109fe6060f1SDimitry Andric                 const MCInstrInfo &MII, const MCTargetOptions &Options)
110fe6060f1SDimitry Andric       : MCTargetAsmParser(Options, STI, MII) {
111fe6060f1SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
112fe6060f1SDimitry Andric   }
113fe6060f1SDimitry Andric };
114fe6060f1SDimitry Andric 
115fe6060f1SDimitry Andric /// Instances of this class represent a parsed machine instruction.
116fe6060f1SDimitry Andric struct CSKYOperand : public MCParsedAsmOperand {
117349cc55cSDimitry Andric 
118fe6060f1SDimitry Andric   enum KindTy {
119fe6060f1SDimitry Andric     Token,
120fe6060f1SDimitry Andric     Register,
121fe6060f1SDimitry Andric     Immediate,
122349cc55cSDimitry Andric     RegisterSeq,
123349cc55cSDimitry Andric     CPOP,
124349cc55cSDimitry Andric     RegisterList
125fe6060f1SDimitry Andric   } Kind;
126fe6060f1SDimitry Andric 
127fe6060f1SDimitry Andric   struct RegOp {
128fe6060f1SDimitry Andric     unsigned RegNum;
129fe6060f1SDimitry Andric   };
130fe6060f1SDimitry Andric 
131fe6060f1SDimitry Andric   struct ImmOp {
132fe6060f1SDimitry Andric     const MCExpr *Val;
133fe6060f1SDimitry Andric   };
134fe6060f1SDimitry Andric 
135349cc55cSDimitry Andric   struct ConstpoolOp {
136349cc55cSDimitry Andric     const MCExpr *Val;
137349cc55cSDimitry Andric   };
138349cc55cSDimitry Andric 
139349cc55cSDimitry Andric   struct RegSeqOp {
140349cc55cSDimitry Andric     unsigned RegNumFrom;
141349cc55cSDimitry Andric     unsigned RegNumTo;
142349cc55cSDimitry Andric   };
143349cc55cSDimitry Andric 
144349cc55cSDimitry Andric   struct RegListOp {
145349cc55cSDimitry Andric     unsigned List1From = 0;
146349cc55cSDimitry Andric     unsigned List1To = 0;
147349cc55cSDimitry Andric     unsigned List2From = 0;
148349cc55cSDimitry Andric     unsigned List2To = 0;
149349cc55cSDimitry Andric     unsigned List3From = 0;
150349cc55cSDimitry Andric     unsigned List3To = 0;
151349cc55cSDimitry Andric     unsigned List4From = 0;
152349cc55cSDimitry Andric     unsigned List4To = 0;
153349cc55cSDimitry Andric   };
154349cc55cSDimitry Andric 
155fe6060f1SDimitry Andric   SMLoc StartLoc, EndLoc;
156fe6060f1SDimitry Andric   union {
157fe6060f1SDimitry Andric     StringRef Tok;
158fe6060f1SDimitry Andric     RegOp Reg;
159fe6060f1SDimitry Andric     ImmOp Imm;
160349cc55cSDimitry Andric     ConstpoolOp CPool;
161349cc55cSDimitry Andric     RegSeqOp RegSeq;
162349cc55cSDimitry Andric     RegListOp RegList;
163fe6060f1SDimitry Andric   };
164fe6060f1SDimitry Andric 
165fe6060f1SDimitry Andric   CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
166fe6060f1SDimitry Andric 
167fe6060f1SDimitry Andric public:
168fe6060f1SDimitry Andric   CSKYOperand(const CSKYOperand &o) : MCParsedAsmOperand() {
169fe6060f1SDimitry Andric     Kind = o.Kind;
170fe6060f1SDimitry Andric     StartLoc = o.StartLoc;
171fe6060f1SDimitry Andric     EndLoc = o.EndLoc;
172fe6060f1SDimitry Andric     switch (Kind) {
173fe6060f1SDimitry Andric     case Register:
174fe6060f1SDimitry Andric       Reg = o.Reg;
175fe6060f1SDimitry Andric       break;
176349cc55cSDimitry Andric     case RegisterSeq:
177349cc55cSDimitry Andric       RegSeq = o.RegSeq;
178349cc55cSDimitry Andric       break;
179349cc55cSDimitry Andric     case CPOP:
180349cc55cSDimitry Andric       CPool = o.CPool;
181349cc55cSDimitry Andric       break;
182fe6060f1SDimitry Andric     case Immediate:
183fe6060f1SDimitry Andric       Imm = o.Imm;
184fe6060f1SDimitry Andric       break;
185fe6060f1SDimitry Andric     case Token:
186fe6060f1SDimitry Andric       Tok = o.Tok;
187fe6060f1SDimitry Andric       break;
188349cc55cSDimitry Andric     case RegisterList:
189349cc55cSDimitry Andric       RegList = o.RegList;
190349cc55cSDimitry Andric       break;
191fe6060f1SDimitry Andric     }
192fe6060f1SDimitry Andric   }
193fe6060f1SDimitry Andric 
194fe6060f1SDimitry Andric   bool isToken() const override { return Kind == Token; }
195fe6060f1SDimitry Andric   bool isReg() const override { return Kind == Register; }
196fe6060f1SDimitry Andric   bool isImm() const override { return Kind == Immediate; }
197349cc55cSDimitry Andric   bool isRegisterSeq() const { return Kind == RegisterSeq; }
198349cc55cSDimitry Andric   bool isRegisterList() const { return Kind == RegisterList; }
199349cc55cSDimitry Andric   bool isConstPoolOp() const { return Kind == CPOP; }
200349cc55cSDimitry Andric 
201fe6060f1SDimitry Andric   bool isMem() const override { return false; }
202fe6060f1SDimitry Andric 
203fe6060f1SDimitry Andric   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
204fe6060f1SDimitry Andric     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
205fe6060f1SDimitry Andric       Imm = CE->getValue();
206fe6060f1SDimitry Andric       return true;
207fe6060f1SDimitry Andric     }
208fe6060f1SDimitry Andric 
209fe6060f1SDimitry Andric     return false;
210fe6060f1SDimitry Andric   }
211fe6060f1SDimitry Andric 
212fe6060f1SDimitry Andric   template <unsigned num, unsigned shift = 0> bool isUImm() 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 && isShiftedUInt<num, shift>(Imm);
219fe6060f1SDimitry Andric   }
220fe6060f1SDimitry Andric 
221fe6060f1SDimitry Andric   template <unsigned num> bool isOImm() const {
222fe6060f1SDimitry Andric     if (!isImm())
223fe6060f1SDimitry Andric       return false;
224fe6060f1SDimitry Andric 
225fe6060f1SDimitry Andric     int64_t Imm;
226fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
227fe6060f1SDimitry Andric     return IsConstantImm && isUInt<num>(Imm - 1);
228fe6060f1SDimitry Andric   }
229fe6060f1SDimitry Andric 
230fe6060f1SDimitry Andric   template <unsigned num, unsigned shift = 0> bool isSImm() const {
231fe6060f1SDimitry Andric     if (!isImm())
232fe6060f1SDimitry Andric       return false;
233fe6060f1SDimitry Andric 
234fe6060f1SDimitry Andric     int64_t Imm;
235fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
236fe6060f1SDimitry Andric     return IsConstantImm && isShiftedInt<num, shift>(Imm);
237fe6060f1SDimitry Andric   }
238fe6060f1SDimitry Andric 
239349cc55cSDimitry Andric   bool isUImm1() const { return isUImm<1>(); }
240fe6060f1SDimitry Andric   bool isUImm2() const { return isUImm<2>(); }
241349cc55cSDimitry Andric   bool isUImm3() const { return isUImm<3>(); }
242349cc55cSDimitry Andric   bool isUImm4() const { return isUImm<4>(); }
243fe6060f1SDimitry Andric   bool isUImm5() const { return isUImm<5>(); }
244349cc55cSDimitry Andric   bool isUImm6() const { return isUImm<6>(); }
245349cc55cSDimitry Andric   bool isUImm7() const { return isUImm<7>(); }
246349cc55cSDimitry Andric   bool isUImm8() const { return isUImm<8>(); }
247fe6060f1SDimitry Andric   bool isUImm12() const { return isUImm<12>(); }
248fe6060f1SDimitry Andric   bool isUImm16() const { return isUImm<16>(); }
249349cc55cSDimitry Andric   bool isUImm20() const { return isUImm<20>(); }
250349cc55cSDimitry Andric   bool isUImm24() const { return isUImm<24>(); }
251fe6060f1SDimitry Andric 
252349cc55cSDimitry Andric   bool isOImm3() const { return isOImm<3>(); }
253349cc55cSDimitry Andric   bool isOImm4() const { return isOImm<4>(); }
254349cc55cSDimitry Andric   bool isOImm5() const { return isOImm<5>(); }
255349cc55cSDimitry Andric   bool isOImm6() const { return isOImm<6>(); }
256349cc55cSDimitry Andric   bool isOImm8() const { return isOImm<8>(); }
257fe6060f1SDimitry Andric   bool isOImm12() const { return isOImm<12>(); }
258fe6060f1SDimitry Andric   bool isOImm16() const { return isOImm<16>(); }
259fe6060f1SDimitry Andric 
260349cc55cSDimitry Andric   bool isSImm8() const { return isSImm<8>(); }
261349cc55cSDimitry Andric 
262349cc55cSDimitry Andric   bool isUImm5Shift1() { return isUImm<5, 1>(); }
263349cc55cSDimitry Andric   bool isUImm5Shift2() { return isUImm<5, 2>(); }
264349cc55cSDimitry Andric   bool isUImm7Shift1() { return isUImm<7, 1>(); }
265349cc55cSDimitry Andric   bool isUImm7Shift2() { return isUImm<7, 2>(); }
266349cc55cSDimitry Andric   bool isUImm7Shift3() { return isUImm<7, 3>(); }
267349cc55cSDimitry Andric   bool isUImm8Shift2() { return isUImm<8, 2>(); }
268349cc55cSDimitry Andric   bool isUImm8Shift3() { return isUImm<8, 3>(); }
269349cc55cSDimitry Andric   bool isUImm8Shift8() { return isUImm<8, 8>(); }
270349cc55cSDimitry Andric   bool isUImm8Shift16() { return isUImm<8, 16>(); }
271349cc55cSDimitry Andric   bool isUImm8Shift24() { return isUImm<8, 24>(); }
272fe6060f1SDimitry Andric   bool isUImm12Shift1() { return isUImm<12, 1>(); }
273fe6060f1SDimitry Andric   bool isUImm12Shift2() { return isUImm<12, 2>(); }
274349cc55cSDimitry Andric   bool isUImm16Shift8() { return isUImm<16, 8>(); }
275349cc55cSDimitry Andric   bool isUImm16Shift16() { return isUImm<16, 16>(); }
276349cc55cSDimitry Andric   bool isUImm24Shift8() { return isUImm<24, 8>(); }
277fe6060f1SDimitry Andric 
278fe6060f1SDimitry Andric   bool isSImm16Shift1() { return isSImm<16, 1>(); }
279fe6060f1SDimitry Andric 
280349cc55cSDimitry Andric   bool isCSKYSymbol() const { return isImm(); }
281349cc55cSDimitry Andric 
282349cc55cSDimitry Andric   bool isConstpool() const { return isConstPoolOp(); }
283349cc55cSDimitry Andric   bool isDataSymbol() const { return isConstPoolOp(); }
284349cc55cSDimitry Andric 
285349cc55cSDimitry Andric   bool isPSRFlag() const {
286fe6060f1SDimitry Andric     int64_t Imm;
287349cc55cSDimitry Andric     // Must be of 'immediate' type and a constant.
288349cc55cSDimitry Andric     if (!isImm() || !evaluateConstantImm(getImm(), Imm))
289349cc55cSDimitry Andric       return false;
290349cc55cSDimitry Andric 
291349cc55cSDimitry Andric     return isUInt<5>(Imm);
292349cc55cSDimitry Andric   }
293349cc55cSDimitry Andric 
294349cc55cSDimitry Andric   template <unsigned MIN, unsigned MAX> bool isRegSeqTemplate() const {
295349cc55cSDimitry Andric     if (!isRegisterSeq())
296349cc55cSDimitry Andric       return false;
297349cc55cSDimitry Andric 
298349cc55cSDimitry Andric     std::pair<unsigned, unsigned> regSeq = getRegSeq();
299349cc55cSDimitry Andric 
300349cc55cSDimitry Andric     return MIN <= regSeq.first && regSeq.first <= regSeq.second &&
301349cc55cSDimitry Andric            regSeq.second <= MAX;
302349cc55cSDimitry Andric   }
303349cc55cSDimitry Andric 
304349cc55cSDimitry Andric   bool isRegSeq() const { return isRegSeqTemplate<CSKY::R0, CSKY::R31>(); }
305349cc55cSDimitry Andric 
306*04eeddc0SDimitry Andric   bool isRegSeqV1() const {
307*04eeddc0SDimitry Andric     return isRegSeqTemplate<CSKY::F0_32, CSKY::F15_32>();
308*04eeddc0SDimitry Andric   }
309*04eeddc0SDimitry Andric 
310*04eeddc0SDimitry Andric   bool isRegSeqV2() const {
311*04eeddc0SDimitry Andric     return isRegSeqTemplate<CSKY::F0_32, CSKY::F31_32>();
312*04eeddc0SDimitry Andric   }
313*04eeddc0SDimitry Andric 
314349cc55cSDimitry Andric   static bool isLegalRegList(unsigned from, unsigned to) {
315349cc55cSDimitry Andric     if (from == 0 && to == 0)
316349cc55cSDimitry Andric       return true;
317349cc55cSDimitry Andric 
318349cc55cSDimitry Andric     if (from == to) {
319349cc55cSDimitry Andric       if (from != CSKY::R4 && from != CSKY::R15 && from != CSKY::R16 &&
320349cc55cSDimitry Andric           from != CSKY::R28)
321349cc55cSDimitry Andric         return false;
322349cc55cSDimitry Andric 
323349cc55cSDimitry Andric       return true;
324349cc55cSDimitry Andric     } else {
325349cc55cSDimitry Andric       if (from != CSKY::R4 && from != CSKY::R16)
326349cc55cSDimitry Andric         return false;
327349cc55cSDimitry Andric 
328349cc55cSDimitry Andric       if (from == CSKY::R4 && to > CSKY::R4 && to < CSKY::R12)
329349cc55cSDimitry Andric         return true;
330349cc55cSDimitry Andric       else if (from == CSKY::R16 && to > CSKY::R16 && to < CSKY::R18)
331349cc55cSDimitry Andric         return true;
332349cc55cSDimitry Andric       else
333349cc55cSDimitry Andric         return false;
334349cc55cSDimitry Andric     }
335349cc55cSDimitry Andric   }
336349cc55cSDimitry Andric 
337349cc55cSDimitry Andric   bool isRegList() const {
338349cc55cSDimitry Andric     if (!isRegisterList())
339349cc55cSDimitry Andric       return false;
340349cc55cSDimitry Andric 
341349cc55cSDimitry Andric     auto regList = getRegList();
342349cc55cSDimitry Andric 
343349cc55cSDimitry Andric     if (!isLegalRegList(regList.List1From, regList.List1To))
344349cc55cSDimitry Andric       return false;
345349cc55cSDimitry Andric     if (!isLegalRegList(regList.List2From, regList.List2To))
346349cc55cSDimitry Andric       return false;
347349cc55cSDimitry Andric     if (!isLegalRegList(regList.List3From, regList.List3To))
348349cc55cSDimitry Andric       return false;
349349cc55cSDimitry Andric     if (!isLegalRegList(regList.List4From, regList.List4To))
350349cc55cSDimitry Andric       return false;
351349cc55cSDimitry Andric 
352349cc55cSDimitry Andric     return true;
353349cc55cSDimitry Andric   }
354349cc55cSDimitry Andric 
355349cc55cSDimitry Andric   bool isExtImm6() {
356349cc55cSDimitry Andric     if (!isImm())
357349cc55cSDimitry Andric       return false;
358349cc55cSDimitry Andric 
359349cc55cSDimitry Andric     int64_t Imm;
360349cc55cSDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
361349cc55cSDimitry Andric     if (!IsConstantImm)
362349cc55cSDimitry Andric       return false;
363349cc55cSDimitry Andric 
364349cc55cSDimitry Andric     int uimm4 = Imm & 0xf;
365349cc55cSDimitry Andric 
366349cc55cSDimitry Andric     return isShiftedUInt<6, 0>(Imm) && uimm4 >= 0 && uimm4 <= 14;
367fe6060f1SDimitry Andric   }
368fe6060f1SDimitry Andric 
369fe6060f1SDimitry Andric   /// Gets location of the first token of this operand.
370fe6060f1SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
371fe6060f1SDimitry Andric   /// Gets location of the last token of this operand.
372fe6060f1SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
373fe6060f1SDimitry Andric 
374fe6060f1SDimitry Andric   unsigned getReg() const override {
375fe6060f1SDimitry Andric     assert(Kind == Register && "Invalid type access!");
376fe6060f1SDimitry Andric     return Reg.RegNum;
377fe6060f1SDimitry Andric   }
378fe6060f1SDimitry Andric 
379349cc55cSDimitry Andric   std::pair<unsigned, unsigned> getRegSeq() const {
380349cc55cSDimitry Andric     assert(Kind == RegisterSeq && "Invalid type access!");
381349cc55cSDimitry Andric     return std::pair<unsigned, unsigned>(RegSeq.RegNumFrom, RegSeq.RegNumTo);
382349cc55cSDimitry Andric   }
383349cc55cSDimitry Andric 
384349cc55cSDimitry Andric   RegListOp getRegList() const {
385349cc55cSDimitry Andric     assert(Kind == RegisterList && "Invalid type access!");
386349cc55cSDimitry Andric     return RegList;
387349cc55cSDimitry Andric   }
388349cc55cSDimitry Andric 
389fe6060f1SDimitry Andric   const MCExpr *getImm() const {
390fe6060f1SDimitry Andric     assert(Kind == Immediate && "Invalid type access!");
391fe6060f1SDimitry Andric     return Imm.Val;
392fe6060f1SDimitry Andric   }
393fe6060f1SDimitry Andric 
394349cc55cSDimitry Andric   const MCExpr *getConstpoolOp() const {
395349cc55cSDimitry Andric     assert(Kind == CPOP && "Invalid type access!");
396349cc55cSDimitry Andric     return CPool.Val;
397349cc55cSDimitry Andric   }
398349cc55cSDimitry Andric 
399fe6060f1SDimitry Andric   StringRef getToken() const {
400fe6060f1SDimitry Andric     assert(Kind == Token && "Invalid type access!");
401fe6060f1SDimitry Andric     return Tok;
402fe6060f1SDimitry Andric   }
403fe6060f1SDimitry Andric 
404fe6060f1SDimitry Andric   void print(raw_ostream &OS) const override {
405349cc55cSDimitry Andric     auto RegName = [](unsigned Reg) {
406349cc55cSDimitry Andric       if (Reg)
407349cc55cSDimitry Andric         return CSKYInstPrinter::getRegisterName(Reg);
408349cc55cSDimitry Andric       else
409349cc55cSDimitry Andric         return "noreg";
410349cc55cSDimitry Andric     };
411349cc55cSDimitry Andric 
412fe6060f1SDimitry Andric     switch (Kind) {
413349cc55cSDimitry Andric     case CPOP:
414349cc55cSDimitry Andric       OS << *getConstpoolOp();
415349cc55cSDimitry Andric       break;
416fe6060f1SDimitry Andric     case Immediate:
417fe6060f1SDimitry Andric       OS << *getImm();
418fe6060f1SDimitry Andric       break;
419349cc55cSDimitry Andric     case KindTy::Register:
420349cc55cSDimitry Andric       OS << "<register " << RegName(getReg()) << ">";
421349cc55cSDimitry Andric       break;
422349cc55cSDimitry Andric     case RegisterSeq:
423349cc55cSDimitry Andric       OS << "<register-seq ";
424349cc55cSDimitry Andric       OS << RegName(getRegSeq().first) << "-" << RegName(getRegSeq().second)
425349cc55cSDimitry Andric          << ">";
426349cc55cSDimitry Andric       break;
427349cc55cSDimitry Andric     case RegisterList:
428349cc55cSDimitry Andric       OS << "<register-list ";
429349cc55cSDimitry Andric       OS << RegName(getRegList().List1From) << "-"
430349cc55cSDimitry Andric          << RegName(getRegList().List1To) << ",";
431349cc55cSDimitry Andric       OS << RegName(getRegList().List2From) << "-"
432349cc55cSDimitry Andric          << RegName(getRegList().List2To) << ",";
433349cc55cSDimitry Andric       OS << RegName(getRegList().List3From) << "-"
434349cc55cSDimitry Andric          << RegName(getRegList().List3To) << ",";
435349cc55cSDimitry Andric       OS << RegName(getRegList().List4From) << "-"
436349cc55cSDimitry Andric          << RegName(getRegList().List4To);
437fe6060f1SDimitry Andric       break;
438fe6060f1SDimitry Andric     case Token:
439fe6060f1SDimitry Andric       OS << "'" << getToken() << "'";
440fe6060f1SDimitry Andric       break;
441fe6060f1SDimitry Andric     }
442fe6060f1SDimitry Andric   }
443fe6060f1SDimitry Andric 
444fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createToken(StringRef Str, SMLoc S) {
445fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Token);
446fe6060f1SDimitry Andric     Op->Tok = Str;
447fe6060f1SDimitry Andric     Op->StartLoc = S;
448fe6060f1SDimitry Andric     Op->EndLoc = S;
449fe6060f1SDimitry Andric     return Op;
450fe6060f1SDimitry Andric   }
451fe6060f1SDimitry Andric 
452fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createReg(unsigned RegNo, SMLoc S,
453fe6060f1SDimitry Andric                                                 SMLoc E) {
454fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Register);
455fe6060f1SDimitry Andric     Op->Reg.RegNum = RegNo;
456fe6060f1SDimitry Andric     Op->StartLoc = S;
457fe6060f1SDimitry Andric     Op->EndLoc = E;
458fe6060f1SDimitry Andric     return Op;
459fe6060f1SDimitry Andric   }
460fe6060f1SDimitry Andric 
461349cc55cSDimitry Andric   static std::unique_ptr<CSKYOperand> createRegSeq(unsigned RegNoFrom,
462349cc55cSDimitry Andric                                                    unsigned RegNoTo, SMLoc S) {
463349cc55cSDimitry Andric     auto Op = std::make_unique<CSKYOperand>(RegisterSeq);
464349cc55cSDimitry Andric     Op->RegSeq.RegNumFrom = RegNoFrom;
465349cc55cSDimitry Andric     Op->RegSeq.RegNumTo = RegNoTo;
466349cc55cSDimitry Andric     Op->StartLoc = S;
467349cc55cSDimitry Andric     Op->EndLoc = S;
468349cc55cSDimitry Andric     return Op;
469349cc55cSDimitry Andric   }
470349cc55cSDimitry Andric 
471349cc55cSDimitry Andric   static std::unique_ptr<CSKYOperand>
472349cc55cSDimitry Andric   createRegList(SmallVector<unsigned, 4> reglist, SMLoc S) {
473349cc55cSDimitry Andric     auto Op = std::make_unique<CSKYOperand>(RegisterList);
474349cc55cSDimitry Andric     Op->RegList.List1From = 0;
475349cc55cSDimitry Andric     Op->RegList.List1To = 0;
476349cc55cSDimitry Andric     Op->RegList.List2From = 0;
477349cc55cSDimitry Andric     Op->RegList.List2To = 0;
478349cc55cSDimitry Andric     Op->RegList.List3From = 0;
479349cc55cSDimitry Andric     Op->RegList.List3To = 0;
480349cc55cSDimitry Andric     Op->RegList.List4From = 0;
481349cc55cSDimitry Andric     Op->RegList.List4To = 0;
482349cc55cSDimitry Andric 
483349cc55cSDimitry Andric     for (unsigned i = 0; i < reglist.size(); i += 2) {
484349cc55cSDimitry Andric       if (Op->RegList.List1From == 0) {
485349cc55cSDimitry Andric         Op->RegList.List1From = reglist[i];
486349cc55cSDimitry Andric         Op->RegList.List1To = reglist[i + 1];
487349cc55cSDimitry Andric       } else if (Op->RegList.List2From == 0) {
488349cc55cSDimitry Andric         Op->RegList.List2From = reglist[i];
489349cc55cSDimitry Andric         Op->RegList.List2To = reglist[i + 1];
490349cc55cSDimitry Andric       } else if (Op->RegList.List3From == 0) {
491349cc55cSDimitry Andric         Op->RegList.List3From = reglist[i];
492349cc55cSDimitry Andric         Op->RegList.List3To = reglist[i + 1];
493349cc55cSDimitry Andric       } else if (Op->RegList.List4From == 0) {
494349cc55cSDimitry Andric         Op->RegList.List4From = reglist[i];
495349cc55cSDimitry Andric         Op->RegList.List4To = reglist[i + 1];
496349cc55cSDimitry Andric       } else {
497349cc55cSDimitry Andric         assert(0);
498349cc55cSDimitry Andric       }
499349cc55cSDimitry Andric     }
500349cc55cSDimitry Andric 
501349cc55cSDimitry Andric     Op->StartLoc = S;
502349cc55cSDimitry Andric     Op->EndLoc = S;
503349cc55cSDimitry Andric     return Op;
504349cc55cSDimitry Andric   }
505349cc55cSDimitry Andric 
506fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S,
507fe6060f1SDimitry Andric                                                 SMLoc E) {
508fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Immediate);
509fe6060f1SDimitry Andric     Op->Imm.Val = Val;
510fe6060f1SDimitry Andric     Op->StartLoc = S;
511fe6060f1SDimitry Andric     Op->EndLoc = E;
512fe6060f1SDimitry Andric     return Op;
513fe6060f1SDimitry Andric   }
514fe6060f1SDimitry Andric 
515349cc55cSDimitry Andric   static std::unique_ptr<CSKYOperand> createConstpoolOp(const MCExpr *Val,
516349cc55cSDimitry Andric                                                         SMLoc S, SMLoc E) {
517349cc55cSDimitry Andric     auto Op = std::make_unique<CSKYOperand>(CPOP);
518349cc55cSDimitry Andric     Op->CPool.Val = Val;
519349cc55cSDimitry Andric     Op->StartLoc = S;
520349cc55cSDimitry Andric     Op->EndLoc = E;
521349cc55cSDimitry Andric     return Op;
522349cc55cSDimitry Andric   }
523349cc55cSDimitry Andric 
524fe6060f1SDimitry Andric   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
525fe6060f1SDimitry Andric     assert(Expr && "Expr shouldn't be null!");
526fe6060f1SDimitry Andric     if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
527fe6060f1SDimitry Andric       Inst.addOperand(MCOperand::createImm(CE->getValue()));
528fe6060f1SDimitry Andric     else
529fe6060f1SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
530fe6060f1SDimitry Andric   }
531fe6060f1SDimitry Andric 
532fe6060f1SDimitry Andric   // Used by the TableGen Code.
533fe6060f1SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
534fe6060f1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
535fe6060f1SDimitry Andric     Inst.addOperand(MCOperand::createReg(getReg()));
536fe6060f1SDimitry Andric   }
537fe6060f1SDimitry Andric 
538fe6060f1SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
539fe6060f1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
540fe6060f1SDimitry Andric     addExpr(Inst, getImm());
541fe6060f1SDimitry Andric   }
542349cc55cSDimitry Andric 
543349cc55cSDimitry Andric   void addConstpoolOperands(MCInst &Inst, unsigned N) const {
544349cc55cSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
545349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createExpr(getConstpoolOp()));
546349cc55cSDimitry Andric   }
547349cc55cSDimitry Andric 
548349cc55cSDimitry Andric   void addRegSeqOperands(MCInst &Inst, unsigned N) const {
549349cc55cSDimitry Andric     assert(N == 2 && "Invalid number of operands!");
550349cc55cSDimitry Andric     auto regSeq = getRegSeq();
551349cc55cSDimitry Andric 
552349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createReg(regSeq.first));
553349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createReg(regSeq.second));
554349cc55cSDimitry Andric   }
555349cc55cSDimitry Andric 
556349cc55cSDimitry Andric   static unsigned getListValue(unsigned ListFrom, unsigned ListTo) {
557349cc55cSDimitry Andric     if (ListFrom == ListTo && ListFrom == CSKY::R15)
558349cc55cSDimitry Andric       return (1 << 4);
559349cc55cSDimitry Andric     else if (ListFrom == ListTo && ListFrom == CSKY::R28)
560349cc55cSDimitry Andric       return (1 << 8);
561349cc55cSDimitry Andric     else if (ListFrom == CSKY::R4)
562349cc55cSDimitry Andric       return ListTo - ListFrom + 1;
563349cc55cSDimitry Andric     else if (ListFrom == CSKY::R16)
564349cc55cSDimitry Andric       return ((ListTo - ListFrom + 1) << 5);
565349cc55cSDimitry Andric     else
566349cc55cSDimitry Andric       return 0;
567349cc55cSDimitry Andric   }
568349cc55cSDimitry Andric 
569349cc55cSDimitry Andric   void addRegListOperands(MCInst &Inst, unsigned N) const {
570349cc55cSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
571349cc55cSDimitry Andric     auto regList = getRegList();
572349cc55cSDimitry Andric 
573349cc55cSDimitry Andric     unsigned V = 0;
574349cc55cSDimitry Andric 
575349cc55cSDimitry Andric     unsigned T = getListValue(regList.List1From, regList.List1To);
576349cc55cSDimitry Andric     if (T != 0)
577349cc55cSDimitry Andric       V = V | T;
578349cc55cSDimitry Andric 
579349cc55cSDimitry Andric     T = getListValue(regList.List2From, regList.List2To);
580349cc55cSDimitry Andric     if (T != 0)
581349cc55cSDimitry Andric       V = V | T;
582349cc55cSDimitry Andric 
583349cc55cSDimitry Andric     T = getListValue(regList.List3From, regList.List3To);
584349cc55cSDimitry Andric     if (T != 0)
585349cc55cSDimitry Andric       V = V | T;
586349cc55cSDimitry Andric 
587349cc55cSDimitry Andric     T = getListValue(regList.List4From, regList.List4To);
588349cc55cSDimitry Andric     if (T != 0)
589349cc55cSDimitry Andric       V = V | T;
590349cc55cSDimitry Andric 
591349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createImm(V));
592349cc55cSDimitry Andric   }
593349cc55cSDimitry Andric 
594349cc55cSDimitry Andric   bool isValidForTie(const CSKYOperand &Other) const {
595349cc55cSDimitry Andric     if (Kind != Other.Kind)
596349cc55cSDimitry Andric       return false;
597349cc55cSDimitry Andric 
598349cc55cSDimitry Andric     switch (Kind) {
599349cc55cSDimitry Andric     default:
600349cc55cSDimitry Andric       llvm_unreachable("Unexpected kind");
601349cc55cSDimitry Andric       return false;
602349cc55cSDimitry Andric     case Register:
603349cc55cSDimitry Andric       return Reg.RegNum == Other.Reg.RegNum;
604349cc55cSDimitry Andric     }
605349cc55cSDimitry Andric   }
606fe6060f1SDimitry Andric };
607fe6060f1SDimitry Andric } // end anonymous namespace.
608fe6060f1SDimitry Andric 
609fe6060f1SDimitry Andric #define GET_REGISTER_MATCHER
610fe6060f1SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME
611fe6060f1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
612fe6060f1SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
613fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
614fe6060f1SDimitry Andric 
615fe6060f1SDimitry Andric static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
616fe6060f1SDimitry Andric                                           unsigned VariantID = 0);
617fe6060f1SDimitry Andric 
618fe6060f1SDimitry Andric bool CSKYAsmParser::generateImmOutOfRangeError(
619fe6060f1SDimitry Andric     OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
620fe6060f1SDimitry Andric     Twine Msg = "immediate must be an integer in the range") {
621fe6060f1SDimitry Andric   SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
622fe6060f1SDimitry Andric   return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
623fe6060f1SDimitry Andric }
624fe6060f1SDimitry Andric 
625fe6060f1SDimitry Andric bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
626fe6060f1SDimitry Andric                                             OperandVector &Operands,
627fe6060f1SDimitry Andric                                             MCStreamer &Out,
628fe6060f1SDimitry Andric                                             uint64_t &ErrorInfo,
629fe6060f1SDimitry Andric                                             bool MatchingInlineAsm) {
630fe6060f1SDimitry Andric   MCInst Inst;
631fe6060f1SDimitry Andric   FeatureBitset MissingFeatures;
632fe6060f1SDimitry Andric 
633fe6060f1SDimitry Andric   auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
634fe6060f1SDimitry Andric                                      MatchingInlineAsm);
635fe6060f1SDimitry Andric   switch (Result) {
636fe6060f1SDimitry Andric   default:
637fe6060f1SDimitry Andric     break;
638fe6060f1SDimitry Andric   case Match_Success:
639349cc55cSDimitry Andric     return processInstruction(Inst, IDLoc, Operands, Out);
640fe6060f1SDimitry Andric   case Match_MissingFeature: {
641fe6060f1SDimitry Andric     assert(MissingFeatures.any() && "Unknown missing features!");
642fe6060f1SDimitry Andric     ListSeparator LS;
643fe6060f1SDimitry Andric     std::string Msg = "instruction requires the following: ";
644fe6060f1SDimitry Andric     for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
645fe6060f1SDimitry Andric       if (MissingFeatures[i]) {
646fe6060f1SDimitry Andric         Msg += LS;
647fe6060f1SDimitry Andric         Msg += getSubtargetFeatureName(i);
648fe6060f1SDimitry Andric       }
649fe6060f1SDimitry Andric     }
650fe6060f1SDimitry Andric     return Error(IDLoc, Msg);
651fe6060f1SDimitry Andric   }
652fe6060f1SDimitry Andric   case Match_MnemonicFail: {
653fe6060f1SDimitry Andric     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
654fe6060f1SDimitry Andric     std::string Suggestion =
655fe6060f1SDimitry Andric         CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS);
656fe6060f1SDimitry Andric     return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
657fe6060f1SDimitry Andric   }
658fe6060f1SDimitry Andric   case Match_InvalidTiedOperand:
659fe6060f1SDimitry Andric   case Match_InvalidOperand: {
660fe6060f1SDimitry Andric     SMLoc ErrorLoc = IDLoc;
661fe6060f1SDimitry Andric     if (ErrorInfo != ~0U) {
662fe6060f1SDimitry Andric       if (ErrorInfo >= Operands.size())
663fe6060f1SDimitry Andric         return Error(ErrorLoc, "too few operands for instruction");
664fe6060f1SDimitry Andric 
665fe6060f1SDimitry Andric       ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
666fe6060f1SDimitry Andric       if (ErrorLoc == SMLoc())
667fe6060f1SDimitry Andric         ErrorLoc = IDLoc;
668fe6060f1SDimitry Andric     }
669fe6060f1SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
670fe6060f1SDimitry Andric   }
671fe6060f1SDimitry Andric   }
672fe6060f1SDimitry Andric 
673fe6060f1SDimitry Andric   // Handle the case when the error message is of specific type
674fe6060f1SDimitry Andric   // other than the generic Match_InvalidOperand, and the
675fe6060f1SDimitry Andric   // corresponding operand is missing.
676fe6060f1SDimitry Andric   if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
677fe6060f1SDimitry Andric     SMLoc ErrorLoc = IDLoc;
678fe6060f1SDimitry Andric     if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
679fe6060f1SDimitry Andric       return Error(ErrorLoc, "too few operands for instruction");
680fe6060f1SDimitry Andric   }
681fe6060f1SDimitry Andric 
682fe6060f1SDimitry Andric   switch (Result) {
683fe6060f1SDimitry Andric   default:
684fe6060f1SDimitry Andric     break;
685349cc55cSDimitry Andric   case Match_InvalidSImm8:
686349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 7),
687349cc55cSDimitry Andric                                       (1 << 7) - 1);
688349cc55cSDimitry Andric   case Match_InvalidOImm3:
689349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 3));
690349cc55cSDimitry Andric   case Match_InvalidOImm4:
691349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 4));
692349cc55cSDimitry Andric   case Match_InvalidOImm5:
693349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
694349cc55cSDimitry Andric   case Match_InvalidOImm6:
695349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6));
696349cc55cSDimitry Andric   case Match_InvalidOImm8:
697349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 8));
698fe6060f1SDimitry Andric   case Match_InvalidOImm12:
699fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12));
700fe6060f1SDimitry Andric   case Match_InvalidOImm16:
701fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16));
702349cc55cSDimitry Andric   case Match_InvalidUImm1:
703349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
704fe6060f1SDimitry Andric   case Match_InvalidUImm2:
705fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
706349cc55cSDimitry Andric   case Match_InvalidUImm3:
707349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
708349cc55cSDimitry Andric   case Match_InvalidUImm4:
709349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
710fe6060f1SDimitry Andric   case Match_InvalidUImm5:
711fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
712349cc55cSDimitry Andric   case Match_InvalidUImm6:
713349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
714349cc55cSDimitry Andric   case Match_InvalidUImm7:
715349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
716349cc55cSDimitry Andric   case Match_InvalidUImm8:
717349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
718fe6060f1SDimitry Andric   case Match_InvalidUImm12:
719fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
720349cc55cSDimitry Andric   case Match_InvalidUImm16:
721349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
722349cc55cSDimitry Andric   case Match_InvalidUImm5Shift1:
723349cc55cSDimitry Andric     return generateImmOutOfRangeError(
724349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 5) - 2,
725349cc55cSDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
726fe6060f1SDimitry Andric   case Match_InvalidUImm12Shift1:
727fe6060f1SDimitry Andric     return generateImmOutOfRangeError(
728fe6060f1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 12) - 2,
729fe6060f1SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
730349cc55cSDimitry Andric   case Match_InvalidUImm5Shift2:
731349cc55cSDimitry Andric     return generateImmOutOfRangeError(
732349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 5) - 4,
733349cc55cSDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
734349cc55cSDimitry Andric   case Match_InvalidUImm7Shift1:
735349cc55cSDimitry Andric     return generateImmOutOfRangeError(
736349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 7) - 2,
737349cc55cSDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
738349cc55cSDimitry Andric   case Match_InvalidUImm7Shift2:
739349cc55cSDimitry Andric     return generateImmOutOfRangeError(
740349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 7) - 4,
741349cc55cSDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
742349cc55cSDimitry Andric   case Match_InvalidUImm8Shift2:
743349cc55cSDimitry Andric     return generateImmOutOfRangeError(
744349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 4,
745349cc55cSDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
746349cc55cSDimitry Andric   case Match_InvalidUImm8Shift3:
747349cc55cSDimitry Andric     return generateImmOutOfRangeError(
748349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 8,
749349cc55cSDimitry Andric         "immediate must be a multiple of 8 bytes in the range");
750349cc55cSDimitry Andric   case Match_InvalidUImm8Shift8:
751349cc55cSDimitry Andric     return generateImmOutOfRangeError(
752349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 256,
753349cc55cSDimitry Andric         "immediate must be a multiple of 256 bytes in the range");
754fe6060f1SDimitry Andric   case Match_InvalidUImm12Shift2:
755fe6060f1SDimitry Andric     return generateImmOutOfRangeError(
756fe6060f1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 12) - 4,
757fe6060f1SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
758fe6060f1SDimitry Andric   case Match_InvalidCSKYSymbol: {
759fe6060f1SDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
760fe6060f1SDimitry Andric     return Error(ErrorLoc, "operand must be a symbol name");
761fe6060f1SDimitry Andric   }
762fe6060f1SDimitry Andric   case Match_InvalidConstpool: {
763fe6060f1SDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
764fe6060f1SDimitry Andric     return Error(ErrorLoc, "operand must be a constpool symbol name");
765fe6060f1SDimitry Andric   }
766349cc55cSDimitry Andric   case Match_InvalidPSRFlag: {
767349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
768349cc55cSDimitry Andric     return Error(ErrorLoc, "psrset operand is not valid");
769349cc55cSDimitry Andric   }
770349cc55cSDimitry Andric   case Match_InvalidRegSeq: {
771349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
772349cc55cSDimitry Andric     return Error(ErrorLoc, "Register sequence is not valid");
773349cc55cSDimitry Andric   }
774349cc55cSDimitry Andric   case Match_InvalidRegOutOfRange: {
775349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
776349cc55cSDimitry Andric     return Error(ErrorLoc, "register is out of range");
777349cc55cSDimitry Andric   }
778349cc55cSDimitry Andric   case Match_RequiresSameSrcAndDst: {
779349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
780349cc55cSDimitry Andric     return Error(ErrorLoc, "src and dst operand must be same");
781349cc55cSDimitry Andric   }
782349cc55cSDimitry Andric   case Match_InvalidRegList: {
783349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
784349cc55cSDimitry Andric     return Error(ErrorLoc, "invalid register list");
785349cc55cSDimitry Andric   }
786349cc55cSDimitry Andric   }
787349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "Result = " << Result);
788349cc55cSDimitry Andric   llvm_unreachable("Unknown match type detected!");
789fe6060f1SDimitry Andric }
790fe6060f1SDimitry Andric 
791349cc55cSDimitry Andric bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
792349cc55cSDimitry Andric                                        OperandVector &Operands,
793349cc55cSDimitry Andric                                        MCStreamer &Out) {
794349cc55cSDimitry Andric 
7950eae32dcSDimitry Andric   switch (Inst.getOpcode()) {
7960eae32dcSDimitry Andric   default:
7970eae32dcSDimitry Andric     break;
7980eae32dcSDimitry Andric   case CSKY::LDQ32:
7990eae32dcSDimitry Andric   case CSKY::STQ32:
800349cc55cSDimitry Andric     if (Inst.getOperand(1).getReg() != CSKY::R4 ||
801349cc55cSDimitry Andric         Inst.getOperand(2).getReg() != CSKY::R7) {
802349cc55cSDimitry Andric       return Error(IDLoc, "Register sequence is not valid. 'r4-r7' expected");
803349cc55cSDimitry Andric     }
804349cc55cSDimitry Andric     Inst.setOpcode(Inst.getOpcode() == CSKY::LDQ32 ? CSKY::LDM32 : CSKY::STM32);
8050eae32dcSDimitry Andric     break;
8060eae32dcSDimitry Andric   case CSKY::SEXT32:
8070eae32dcSDimitry Andric   case CSKY::ZEXT32:
808349cc55cSDimitry Andric     if (Inst.getOperand(2).getImm() < Inst.getOperand(3).getImm())
809349cc55cSDimitry Andric       return Error(IDLoc, "msb must be greater or equal to lsb");
8100eae32dcSDimitry Andric     break;
8110eae32dcSDimitry Andric   case CSKY::INS32:
812349cc55cSDimitry Andric     if (Inst.getOperand(3).getImm() < Inst.getOperand(4).getImm())
813349cc55cSDimitry Andric       return Error(IDLoc, "msb must be greater or equal to lsb");
8140eae32dcSDimitry Andric     break;
8150eae32dcSDimitry Andric   case CSKY::IDLY32:
816349cc55cSDimitry Andric     if (Inst.getOperand(0).getImm() > 32 || Inst.getOperand(0).getImm() < 0)
817349cc55cSDimitry Andric       return Error(IDLoc, "n must be in range [0,32]");
8180eae32dcSDimitry Andric     break;
8190eae32dcSDimitry Andric   case CSKY::ADDC32:
8200eae32dcSDimitry Andric   case CSKY::SUBC32:
8210eae32dcSDimitry Andric   case CSKY::ADDC16:
8220eae32dcSDimitry Andric   case CSKY::SUBC16:
8230eae32dcSDimitry Andric     Inst.erase(std::next(Inst.begin()));
8240eae32dcSDimitry Andric     Inst.erase(std::prev(Inst.end()));
8250eae32dcSDimitry Andric     Inst.insert(std::next(Inst.begin()), MCOperand::createReg(CSKY::C));
8260eae32dcSDimitry Andric     Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
8270eae32dcSDimitry Andric     break;
8280eae32dcSDimitry Andric   case CSKY::CMPNEI32:
8290eae32dcSDimitry Andric   case CSKY::CMPNEI16:
8300eae32dcSDimitry Andric   case CSKY::CMPNE32:
8310eae32dcSDimitry Andric   case CSKY::CMPNE16:
8320eae32dcSDimitry Andric   case CSKY::CMPHSI32:
8330eae32dcSDimitry Andric   case CSKY::CMPHSI16:
8340eae32dcSDimitry Andric   case CSKY::CMPHS32:
8350eae32dcSDimitry Andric   case CSKY::CMPHS16:
8360eae32dcSDimitry Andric   case CSKY::CMPLTI32:
8370eae32dcSDimitry Andric   case CSKY::CMPLTI16:
8380eae32dcSDimitry Andric   case CSKY::CMPLT32:
8390eae32dcSDimitry Andric   case CSKY::CMPLT16:
8400eae32dcSDimitry Andric   case CSKY::BTSTI32:
8410eae32dcSDimitry Andric     Inst.erase(Inst.begin());
8420eae32dcSDimitry Andric     Inst.insert(Inst.begin(), MCOperand::createReg(CSKY::C));
8430eae32dcSDimitry Andric     break;
8440eae32dcSDimitry Andric   case CSKY::MVCV32:
8450eae32dcSDimitry Andric     Inst.erase(std::next(Inst.begin()));
8460eae32dcSDimitry Andric     Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
8470eae32dcSDimitry Andric     break;
848349cc55cSDimitry Andric   }
849349cc55cSDimitry Andric 
8500eae32dcSDimitry Andric   emitToStreamer(Out, Inst);
851349cc55cSDimitry Andric   return false;
852fe6060f1SDimitry Andric }
853fe6060f1SDimitry Andric 
854fe6060f1SDimitry Andric // Attempts to match Name as a register (either using the default name or
855fe6060f1SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon
856fe6060f1SDimitry Andric // failure, returns true and sets RegNo to 0.
857349cc55cSDimitry Andric static bool matchRegisterNameHelper(const MCSubtargetInfo &STI,
858349cc55cSDimitry Andric                                     MCRegister &RegNo, StringRef Name) {
859fe6060f1SDimitry Andric   RegNo = MatchRegisterName(Name);
860fe6060f1SDimitry Andric 
861fe6060f1SDimitry Andric   if (RegNo == CSKY::NoRegister)
862fe6060f1SDimitry Andric     RegNo = MatchRegisterAltName(Name);
863fe6060f1SDimitry Andric 
864fe6060f1SDimitry Andric   return RegNo == CSKY::NoRegister;
865fe6060f1SDimitry Andric }
866fe6060f1SDimitry Andric 
867fe6060f1SDimitry Andric bool CSKYAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
868fe6060f1SDimitry Andric                                   SMLoc &EndLoc) {
869fe6060f1SDimitry Andric   const AsmToken &Tok = getParser().getTok();
870fe6060f1SDimitry Andric   StartLoc = Tok.getLoc();
871fe6060f1SDimitry Andric   EndLoc = Tok.getEndLoc();
872fe6060f1SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
873fe6060f1SDimitry Andric 
874349cc55cSDimitry Andric   if (!matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name)) {
875fe6060f1SDimitry Andric     getParser().Lex(); // Eat identifier token.
876fe6060f1SDimitry Andric     return false;
877fe6060f1SDimitry Andric   }
878fe6060f1SDimitry Andric 
879349cc55cSDimitry Andric   return MatchOperand_NoMatch;
880fe6060f1SDimitry Andric }
881fe6060f1SDimitry Andric 
882fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegister(OperandVector &Operands) {
883fe6060f1SDimitry Andric   SMLoc S = getLoc();
884fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
885fe6060f1SDimitry Andric 
886fe6060f1SDimitry Andric   switch (getLexer().getKind()) {
887fe6060f1SDimitry Andric   default:
888fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
889fe6060f1SDimitry Andric   case AsmToken::Identifier: {
890fe6060f1SDimitry Andric     StringRef Name = getLexer().getTok().getIdentifier();
891fe6060f1SDimitry Andric     MCRegister RegNo;
892fe6060f1SDimitry Andric 
893349cc55cSDimitry Andric     if (matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name))
894fe6060f1SDimitry Andric       return MatchOperand_NoMatch;
895fe6060f1SDimitry Andric 
896fe6060f1SDimitry Andric     getLexer().Lex();
897fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createReg(RegNo, S, E));
898fe6060f1SDimitry Andric 
899fe6060f1SDimitry Andric     return MatchOperand_Success;
900fe6060f1SDimitry Andric   }
901fe6060f1SDimitry Andric   }
902fe6060f1SDimitry Andric }
903fe6060f1SDimitry Andric 
904fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) {
905fe6060f1SDimitry Andric   assert(getLexer().is(AsmToken::LParen));
906fe6060f1SDimitry Andric 
907fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken("(", getLoc()));
908fe6060f1SDimitry Andric 
909fe6060f1SDimitry Andric   auto Tok = getParser().Lex(); // Eat '('
910fe6060f1SDimitry Andric 
911fe6060f1SDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success) {
912fe6060f1SDimitry Andric     getLexer().UnLex(Tok);
913fe6060f1SDimitry Andric     Operands.pop_back();
914349cc55cSDimitry Andric     return MatchOperand_NoMatch;
915349cc55cSDimitry Andric   }
916349cc55cSDimitry Andric 
917349cc55cSDimitry Andric   if (getLexer().is(AsmToken::RParen)) {
918349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createToken(")", getLoc()));
919349cc55cSDimitry Andric     getParser().Lex(); // Eat ')'
920349cc55cSDimitry Andric     return MatchOperand_Success;
921fe6060f1SDimitry Andric   }
922fe6060f1SDimitry Andric 
923fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::Comma)) {
924fe6060f1SDimitry Andric     Error(getLoc(), "expected ','");
925fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
926fe6060f1SDimitry Andric   }
927fe6060f1SDimitry Andric 
928fe6060f1SDimitry Andric   getParser().Lex(); // Eat ','
929fe6060f1SDimitry Andric 
930fe6060f1SDimitry Andric   if (parseRegister(Operands) == MatchOperand_Success) {
931fe6060f1SDimitry Andric     if (getLexer().isNot(AsmToken::LessLess)) {
932fe6060f1SDimitry Andric       Error(getLoc(), "expected '<<'");
933fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
934fe6060f1SDimitry Andric     }
935fe6060f1SDimitry Andric 
936fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createToken("<<", getLoc()));
937fe6060f1SDimitry Andric 
938fe6060f1SDimitry Andric     getParser().Lex(); // Eat '<<'
939fe6060f1SDimitry Andric 
940fe6060f1SDimitry Andric     if (parseImmediate(Operands) != MatchOperand_Success) {
941fe6060f1SDimitry Andric       Error(getLoc(), "expected imm");
942fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
943fe6060f1SDimitry Andric     }
944fe6060f1SDimitry Andric 
945fe6060f1SDimitry Andric   } else if (parseImmediate(Operands) != MatchOperand_Success) {
946fe6060f1SDimitry Andric     Error(getLoc(), "expected imm");
947fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
948fe6060f1SDimitry Andric   }
949fe6060f1SDimitry Andric 
950fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::RParen)) {
951fe6060f1SDimitry Andric     Error(getLoc(), "expected ')'");
952fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
953fe6060f1SDimitry Andric   }
954fe6060f1SDimitry Andric 
955fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken(")", getLoc()));
956fe6060f1SDimitry Andric 
957fe6060f1SDimitry Andric   getParser().Lex(); // Eat ')'
958fe6060f1SDimitry Andric 
959fe6060f1SDimitry Andric   return MatchOperand_Success;
960fe6060f1SDimitry Andric }
961fe6060f1SDimitry Andric 
962fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
963fe6060f1SDimitry Andric   switch (getLexer().getKind()) {
964fe6060f1SDimitry Andric   default:
965fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
966fe6060f1SDimitry Andric   case AsmToken::LParen:
967fe6060f1SDimitry Andric   case AsmToken::Minus:
968fe6060f1SDimitry Andric   case AsmToken::Plus:
969fe6060f1SDimitry Andric   case AsmToken::Integer:
970fe6060f1SDimitry Andric   case AsmToken::String:
971fe6060f1SDimitry Andric     break;
972fe6060f1SDimitry Andric   }
973fe6060f1SDimitry Andric 
974fe6060f1SDimitry Andric   const MCExpr *IdVal;
975fe6060f1SDimitry Andric   SMLoc S = getLoc();
976349cc55cSDimitry Andric   if (getParser().parseExpression(IdVal)) {
977349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
978fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
979349cc55cSDimitry Andric   }
980fe6060f1SDimitry Andric 
981fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
982fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createImm(IdVal, S, E));
983fe6060f1SDimitry Andric   return MatchOperand_Success;
984fe6060f1SDimitry Andric }
985fe6060f1SDimitry Andric 
986fe6060f1SDimitry Andric /// Looks at a token type and creates the relevant operand from this
987fe6060f1SDimitry Andric /// information, adding to Operands. If operand was parsed, returns false, else
988fe6060f1SDimitry Andric /// true.
989fe6060f1SDimitry Andric bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
990fe6060f1SDimitry Andric   // Check if the current operand has a custom associated parser, if so, try to
991fe6060f1SDimitry Andric   // custom parse the operand, or fallback to the general approach.
992fe6060f1SDimitry Andric   OperandMatchResultTy Result =
993fe6060f1SDimitry Andric       MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
994fe6060f1SDimitry Andric   if (Result == MatchOperand_Success)
995fe6060f1SDimitry Andric     return false;
996fe6060f1SDimitry Andric   if (Result == MatchOperand_ParseFail)
997fe6060f1SDimitry Andric     return true;
998fe6060f1SDimitry Andric 
999fe6060f1SDimitry Andric   // Attempt to parse token as register
1000349cc55cSDimitry Andric   auto Res = parseRegister(Operands);
1001349cc55cSDimitry Andric   if (Res == MatchOperand_Success)
1002fe6060f1SDimitry Andric     return false;
1003349cc55cSDimitry Andric   else if (Res == MatchOperand_ParseFail)
1004349cc55cSDimitry Andric     return true;
1005fe6060f1SDimitry Andric 
1006fe6060f1SDimitry Andric   // Attempt to parse token as (register, imm)
1007349cc55cSDimitry Andric   if (getLexer().is(AsmToken::LParen)) {
1008349cc55cSDimitry Andric     Res = parseBaseRegImm(Operands);
1009349cc55cSDimitry Andric     if (Res == MatchOperand_Success)
1010fe6060f1SDimitry Andric       return false;
1011349cc55cSDimitry Andric     else if (Res == MatchOperand_ParseFail)
1012349cc55cSDimitry Andric       return true;
1013349cc55cSDimitry Andric   }
1014fe6060f1SDimitry Andric 
1015349cc55cSDimitry Andric   Res = parseImmediate(Operands);
1016349cc55cSDimitry Andric   if (Res == MatchOperand_Success)
1017fe6060f1SDimitry Andric     return false;
1018349cc55cSDimitry Andric   else if (Res == MatchOperand_ParseFail)
1019349cc55cSDimitry Andric     return true;
1020fe6060f1SDimitry Andric 
1021fe6060f1SDimitry Andric   // Finally we have exhausted all options and must declare defeat.
1022fe6060f1SDimitry Andric   Error(getLoc(), "unknown operand");
1023fe6060f1SDimitry Andric   return true;
1024fe6060f1SDimitry Andric }
1025fe6060f1SDimitry Andric 
1026fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
1027fe6060f1SDimitry Andric   SMLoc S = getLoc();
1028fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1029349cc55cSDimitry Andric   const MCExpr *Res;
1030fe6060f1SDimitry Andric 
1031fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
1032fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1033fe6060f1SDimitry Andric 
1034fe6060f1SDimitry Andric   StringRef Identifier;
1035349cc55cSDimitry Andric   AsmToken Tok = getLexer().getTok();
1036349cc55cSDimitry Andric 
1037349cc55cSDimitry Andric   if (getParser().parseIdentifier(Identifier)) {
1038349cc55cSDimitry Andric     Error(getLoc(), "unknown identifier");
1039fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
1040349cc55cSDimitry Andric   }
1041fe6060f1SDimitry Andric 
1042fe6060f1SDimitry Andric   CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
1043fe6060f1SDimitry Andric   if (Identifier.consume_back("@GOT"))
1044fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOT;
1045fe6060f1SDimitry Andric   else if (Identifier.consume_back("@GOTOFF"))
1046fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOTOFF;
1047fe6060f1SDimitry Andric   else if (Identifier.consume_back("@PLT"))
1048fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_PLT;
1049fe6060f1SDimitry Andric   else if (Identifier.consume_back("@GOTPC"))
1050fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOTPC;
1051349cc55cSDimitry Andric   else if (Identifier.consume_back("@TLSGD32"))
1052349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSGD;
1053349cc55cSDimitry Andric   else if (Identifier.consume_back("@GOTTPOFF"))
1054349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSIE;
1055349cc55cSDimitry Andric   else if (Identifier.consume_back("@TPOFF"))
1056349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSLE;
1057349cc55cSDimitry Andric   else if (Identifier.consume_back("@TLSLDM32"))
1058349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSLDM;
1059349cc55cSDimitry Andric   else if (Identifier.consume_back("@TLSLDO32"))
1060349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSLDO;
1061fe6060f1SDimitry Andric 
1062349cc55cSDimitry Andric   MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1063fe6060f1SDimitry Andric 
1064349cc55cSDimitry Andric   if (!Sym)
1065349cc55cSDimitry Andric     Sym = getContext().getOrCreateSymbol(Identifier);
1066349cc55cSDimitry Andric 
1067349cc55cSDimitry Andric   if (Sym->isVariable()) {
1068349cc55cSDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1069349cc55cSDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
1070349cc55cSDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1071349cc55cSDimitry Andric       Error(getLoc(), "unknown symbol");
1072349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1073349cc55cSDimitry Andric     }
1074349cc55cSDimitry Andric     Res = V;
1075349cc55cSDimitry Andric   } else
1076349cc55cSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1077349cc55cSDimitry Andric 
1078349cc55cSDimitry Andric   MCBinaryExpr::Opcode Opcode;
1079349cc55cSDimitry Andric   switch (getLexer().getKind()) {
1080349cc55cSDimitry Andric   default:
1081fe6060f1SDimitry Andric     if (Kind != CSKYMCExpr::VK_CSKY_None)
1082fe6060f1SDimitry Andric       Res = CSKYMCExpr::create(Res, Kind, getContext());
1083fe6060f1SDimitry Andric 
1084fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createImm(Res, S, E));
1085fe6060f1SDimitry Andric     return MatchOperand_Success;
1086349cc55cSDimitry Andric   case AsmToken::Plus:
1087349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Add;
1088349cc55cSDimitry Andric     break;
1089349cc55cSDimitry Andric   case AsmToken::Minus:
1090349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Sub;
1091349cc55cSDimitry Andric     break;
1092349cc55cSDimitry Andric   }
1093349cc55cSDimitry Andric 
1094349cc55cSDimitry Andric   getLexer().Lex(); // eat + or -
1095349cc55cSDimitry Andric 
1096349cc55cSDimitry Andric   const MCExpr *Expr;
1097349cc55cSDimitry Andric   if (getParser().parseExpression(Expr)) {
1098349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1099349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1100349cc55cSDimitry Andric   }
1101349cc55cSDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1102349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createImm(Res, S, E));
1103349cc55cSDimitry Andric   return MatchOperand_Success;
1104349cc55cSDimitry Andric }
1105349cc55cSDimitry Andric 
1106349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parseDataSymbol(OperandVector &Operands) {
1107349cc55cSDimitry Andric   SMLoc S = getLoc();
1108349cc55cSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1109349cc55cSDimitry Andric   const MCExpr *Res;
1110349cc55cSDimitry Andric 
1111349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::LBrac)
1112349cc55cSDimitry Andric     return MatchOperand_NoMatch;
1113349cc55cSDimitry Andric 
1114349cc55cSDimitry Andric   getLexer().Lex(); // Eat '['.
1115349cc55cSDimitry Andric 
1116349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier) {
1117349cc55cSDimitry Andric     const MCExpr *Expr;
1118349cc55cSDimitry Andric     if (getParser().parseExpression(Expr)) {
1119349cc55cSDimitry Andric       Error(getLoc(), "unknown expression");
1120349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1121349cc55cSDimitry Andric     }
1122349cc55cSDimitry Andric 
1123349cc55cSDimitry Andric     if (getLexer().getKind() != AsmToken::RBrac) {
1124349cc55cSDimitry Andric       Error(getLoc(), "expected ]");
1125349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1126349cc55cSDimitry Andric     }
1127349cc55cSDimitry Andric 
1128349cc55cSDimitry Andric     getLexer().Lex(); // Eat ']'.
1129349cc55cSDimitry Andric 
1130349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1131349cc55cSDimitry Andric     return MatchOperand_Success;
1132349cc55cSDimitry Andric   }
1133349cc55cSDimitry Andric 
1134349cc55cSDimitry Andric   AsmToken Tok = getLexer().getTok();
1135349cc55cSDimitry Andric   StringRef Identifier;
1136349cc55cSDimitry Andric 
1137349cc55cSDimitry Andric   if (getParser().parseIdentifier(Identifier)) {
1138349cc55cSDimitry Andric     Error(getLoc(), "unknown identifier " + Identifier);
1139349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1140349cc55cSDimitry Andric   }
1141349cc55cSDimitry Andric 
1142349cc55cSDimitry Andric   CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
1143349cc55cSDimitry Andric   if (Identifier.consume_back("@GOT"))
1144349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4;
1145349cc55cSDimitry Andric   else if (Identifier.consume_back("@PLT"))
1146349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4;
1147349cc55cSDimitry Andric 
1148349cc55cSDimitry Andric   MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1149349cc55cSDimitry Andric 
1150349cc55cSDimitry Andric   if (!Sym)
1151349cc55cSDimitry Andric     Sym = getContext().getOrCreateSymbol(Identifier);
1152349cc55cSDimitry Andric 
1153349cc55cSDimitry Andric   if (Sym->isVariable()) {
1154349cc55cSDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1155349cc55cSDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
1156349cc55cSDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1157349cc55cSDimitry Andric       Error(getLoc(), "unknown symbol");
1158349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1159349cc55cSDimitry Andric     }
1160349cc55cSDimitry Andric     Res = V;
1161349cc55cSDimitry Andric   } else {
1162349cc55cSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1163349cc55cSDimitry Andric   }
1164349cc55cSDimitry Andric 
1165349cc55cSDimitry Andric   MCBinaryExpr::Opcode Opcode;
1166349cc55cSDimitry Andric   switch (getLexer().getKind()) {
1167349cc55cSDimitry Andric   default:
1168349cc55cSDimitry Andric     Error(getLoc(), "unknown symbol");
1169349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1170349cc55cSDimitry Andric   case AsmToken::RBrac:
1171349cc55cSDimitry Andric 
1172349cc55cSDimitry Andric     getLexer().Lex(); // Eat ']'.
1173349cc55cSDimitry Andric 
1174349cc55cSDimitry Andric     if (Kind != CSKYMCExpr::VK_CSKY_None)
1175349cc55cSDimitry Andric       Res = CSKYMCExpr::create(Res, Kind, getContext());
1176349cc55cSDimitry Andric 
1177349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1178349cc55cSDimitry Andric     return MatchOperand_Success;
1179349cc55cSDimitry Andric   case AsmToken::Plus:
1180349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Add;
1181349cc55cSDimitry Andric     break;
1182349cc55cSDimitry Andric   case AsmToken::Minus:
1183349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Sub;
1184349cc55cSDimitry Andric     break;
1185349cc55cSDimitry Andric   }
1186349cc55cSDimitry Andric 
1187349cc55cSDimitry Andric   getLexer().Lex(); // eat + or -
1188349cc55cSDimitry Andric 
1189349cc55cSDimitry Andric   const MCExpr *Expr;
1190349cc55cSDimitry Andric   if (getParser().parseExpression(Expr)) {
1191349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1192349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1193349cc55cSDimitry Andric   }
1194349cc55cSDimitry Andric 
1195349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::RBrac) {
1196349cc55cSDimitry Andric     Error(getLoc(), "expected ']'");
1197349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1198349cc55cSDimitry Andric   }
1199349cc55cSDimitry Andric 
1200349cc55cSDimitry Andric   getLexer().Lex(); // Eat ']'.
1201349cc55cSDimitry Andric 
1202349cc55cSDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1203349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1204349cc55cSDimitry Andric   return MatchOperand_Success;
1205fe6060f1SDimitry Andric }
1206fe6060f1SDimitry Andric 
1207fe6060f1SDimitry Andric OperandMatchResultTy
1208fe6060f1SDimitry Andric CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
1209fe6060f1SDimitry Andric   SMLoc S = getLoc();
1210fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1211349cc55cSDimitry Andric   const MCExpr *Res;
1212fe6060f1SDimitry Andric 
1213fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::LBrac)
1214fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1215fe6060f1SDimitry Andric 
1216fe6060f1SDimitry Andric   getLexer().Lex(); // Eat '['.
1217fe6060f1SDimitry Andric 
1218349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier) {
1219349cc55cSDimitry Andric     const MCExpr *Expr;
1220349cc55cSDimitry Andric     if (getParser().parseExpression(Expr)) {
1221349cc55cSDimitry Andric       Error(getLoc(), "unknown expression");
1222fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
1223349cc55cSDimitry Andric     }
1224fe6060f1SDimitry Andric 
1225349cc55cSDimitry Andric     if (getLexer().getKind() != AsmToken::RBrac) {
1226349cc55cSDimitry Andric       Error(getLoc(), "expected ']'");
1227349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1228349cc55cSDimitry Andric     }
1229fe6060f1SDimitry Andric 
1230fe6060f1SDimitry Andric     getLexer().Lex(); // Eat ']'.
1231fe6060f1SDimitry Andric 
1232349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1233349cc55cSDimitry Andric     return MatchOperand_Success;
1234349cc55cSDimitry Andric   }
1235349cc55cSDimitry Andric 
1236349cc55cSDimitry Andric   AsmToken Tok = getLexer().getTok();
1237349cc55cSDimitry Andric   StringRef Identifier;
1238349cc55cSDimitry Andric 
1239349cc55cSDimitry Andric   if (getParser().parseIdentifier(Identifier)) {
1240349cc55cSDimitry Andric     Error(getLoc(), "unknown identifier");
1241349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1242349cc55cSDimitry Andric   }
1243349cc55cSDimitry Andric 
1244349cc55cSDimitry Andric   MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1245349cc55cSDimitry Andric 
1246349cc55cSDimitry Andric   if (!Sym)
1247349cc55cSDimitry Andric     Sym = getContext().getOrCreateSymbol(Identifier);
1248349cc55cSDimitry Andric 
1249349cc55cSDimitry Andric   if (Sym->isVariable()) {
1250349cc55cSDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1251349cc55cSDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
1252349cc55cSDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1253349cc55cSDimitry Andric       Error(getLoc(), "unknown symbol");
1254349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1255349cc55cSDimitry Andric     }
1256349cc55cSDimitry Andric     Res = V;
1257349cc55cSDimitry Andric   } else {
1258349cc55cSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1259349cc55cSDimitry Andric   }
1260349cc55cSDimitry Andric 
1261349cc55cSDimitry Andric   MCBinaryExpr::Opcode Opcode;
1262349cc55cSDimitry Andric   switch (getLexer().getKind()) {
1263349cc55cSDimitry Andric   default:
1264349cc55cSDimitry Andric     Error(getLoc(), "unknown symbol");
1265349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1266349cc55cSDimitry Andric   case AsmToken::RBrac:
1267349cc55cSDimitry Andric 
1268349cc55cSDimitry Andric     getLexer().Lex(); // Eat ']'.
1269349cc55cSDimitry Andric 
1270349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1271349cc55cSDimitry Andric     return MatchOperand_Success;
1272349cc55cSDimitry Andric   case AsmToken::Plus:
1273349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Add;
1274349cc55cSDimitry Andric     break;
1275349cc55cSDimitry Andric   case AsmToken::Minus:
1276349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Sub;
1277349cc55cSDimitry Andric     break;
1278349cc55cSDimitry Andric   }
1279349cc55cSDimitry Andric 
1280349cc55cSDimitry Andric   getLexer().Lex(); // eat + or -
1281349cc55cSDimitry Andric 
1282349cc55cSDimitry Andric   const MCExpr *Expr;
1283349cc55cSDimitry Andric   if (getParser().parseExpression(Expr)) {
1284349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1285349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1286349cc55cSDimitry Andric   }
1287349cc55cSDimitry Andric 
1288349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::RBrac) {
1289349cc55cSDimitry Andric     Error(getLoc(), "expected ']'");
1290349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1291349cc55cSDimitry Andric   }
1292349cc55cSDimitry Andric 
1293349cc55cSDimitry Andric   getLexer().Lex(); // Eat ']'.
1294349cc55cSDimitry Andric 
1295349cc55cSDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1296349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1297349cc55cSDimitry Andric   return MatchOperand_Success;
1298349cc55cSDimitry Andric }
1299349cc55cSDimitry Andric 
1300349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parsePSRFlag(OperandVector &Operands) {
1301349cc55cSDimitry Andric   SMLoc S = getLoc();
1302349cc55cSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1303349cc55cSDimitry Andric 
1304349cc55cSDimitry Andric   unsigned Flag = 0;
1305349cc55cSDimitry Andric 
1306349cc55cSDimitry Andric   while (getLexer().isNot(AsmToken::EndOfStatement)) {
1307349cc55cSDimitry Andric     StringRef Identifier;
1308349cc55cSDimitry Andric     if (getParser().parseIdentifier(Identifier)) {
1309349cc55cSDimitry Andric       Error(getLoc(), "unknown identifier " + Identifier);
1310349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1311349cc55cSDimitry Andric     }
1312349cc55cSDimitry Andric 
1313349cc55cSDimitry Andric     if (Identifier == "sie")
1314349cc55cSDimitry Andric       Flag = (1 << 4) | Flag;
1315349cc55cSDimitry Andric     else if (Identifier == "ee")
1316349cc55cSDimitry Andric       Flag = (1 << 3) | Flag;
1317349cc55cSDimitry Andric     else if (Identifier == "ie")
1318349cc55cSDimitry Andric       Flag = (1 << 2) | Flag;
1319349cc55cSDimitry Andric     else if (Identifier == "fe")
1320349cc55cSDimitry Andric       Flag = (1 << 1) | Flag;
1321349cc55cSDimitry Andric     else if (Identifier == "af")
1322349cc55cSDimitry Andric       Flag = (1 << 0) | Flag;
1323349cc55cSDimitry Andric     else {
1324349cc55cSDimitry Andric       Error(getLoc(), "expected " + Identifier);
1325349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1326349cc55cSDimitry Andric     }
1327349cc55cSDimitry Andric 
1328349cc55cSDimitry Andric     if (getLexer().is(AsmToken::EndOfStatement))
1329349cc55cSDimitry Andric       break;
1330349cc55cSDimitry Andric 
1331349cc55cSDimitry Andric     if (getLexer().is(AsmToken::Comma)) {
1332349cc55cSDimitry Andric       getLexer().Lex(); // eat ','
1333349cc55cSDimitry Andric     } else {
1334349cc55cSDimitry Andric       Error(getLoc(), "expected ,");
1335349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1336349cc55cSDimitry Andric     }
1337349cc55cSDimitry Andric   }
1338349cc55cSDimitry Andric 
1339349cc55cSDimitry Andric   Operands.push_back(
1340349cc55cSDimitry Andric       CSKYOperand::createImm(MCConstantExpr::create(Flag, getContext()), S, E));
1341349cc55cSDimitry Andric   return MatchOperand_Success;
1342349cc55cSDimitry Andric }
1343349cc55cSDimitry Andric 
1344349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegSeq(OperandVector &Operands) {
1345349cc55cSDimitry Andric   SMLoc S = getLoc();
1346349cc55cSDimitry Andric 
1347349cc55cSDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success)
1348349cc55cSDimitry Andric     return MatchOperand_NoMatch;
1349349cc55cSDimitry Andric 
1350349cc55cSDimitry Andric   auto Ry = Operands.back()->getReg();
1351349cc55cSDimitry Andric   Operands.pop_back();
1352349cc55cSDimitry Andric 
1353349cc55cSDimitry Andric   if (getLexer().isNot(AsmToken::Minus)) {
1354349cc55cSDimitry Andric     Error(getLoc(), "expected '-'");
1355349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1356349cc55cSDimitry Andric   }
1357349cc55cSDimitry Andric 
1358349cc55cSDimitry Andric   getLexer().Lex(); // eat '-'
1359349cc55cSDimitry Andric 
1360349cc55cSDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success) {
1361349cc55cSDimitry Andric     Error(getLoc(), "invalid register");
1362349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1363349cc55cSDimitry Andric   }
1364349cc55cSDimitry Andric 
1365349cc55cSDimitry Andric   auto Rz = Operands.back()->getReg();
1366349cc55cSDimitry Andric   Operands.pop_back();
1367349cc55cSDimitry Andric 
1368349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createRegSeq(Ry, Rz, S));
1369349cc55cSDimitry Andric   return MatchOperand_Success;
1370349cc55cSDimitry Andric }
1371349cc55cSDimitry Andric 
1372349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegList(OperandVector &Operands) {
1373349cc55cSDimitry Andric   SMLoc S = getLoc();
1374349cc55cSDimitry Andric 
1375349cc55cSDimitry Andric   SmallVector<unsigned, 4> reglist;
1376349cc55cSDimitry Andric 
1377349cc55cSDimitry Andric   while (true) {
1378349cc55cSDimitry Andric 
1379349cc55cSDimitry Andric     if (parseRegister(Operands) != MatchOperand_Success) {
1380349cc55cSDimitry Andric       Error(getLoc(), "invalid register");
1381349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1382349cc55cSDimitry Andric     }
1383349cc55cSDimitry Andric 
1384349cc55cSDimitry Andric     auto Ry = Operands.back()->getReg();
1385349cc55cSDimitry Andric     Operands.pop_back();
1386349cc55cSDimitry Andric 
1387349cc55cSDimitry Andric     if (getLexer().is(AsmToken::Minus)) {
1388349cc55cSDimitry Andric       getLexer().Lex(); // eat '-'
1389349cc55cSDimitry Andric 
1390349cc55cSDimitry Andric       if (parseRegister(Operands) != MatchOperand_Success) {
1391349cc55cSDimitry Andric         Error(getLoc(), "invalid register");
1392349cc55cSDimitry Andric         return MatchOperand_ParseFail;
1393349cc55cSDimitry Andric       }
1394349cc55cSDimitry Andric 
1395349cc55cSDimitry Andric       auto Rz = Operands.back()->getReg();
1396349cc55cSDimitry Andric       Operands.pop_back();
1397349cc55cSDimitry Andric 
1398349cc55cSDimitry Andric       reglist.push_back(Ry);
1399349cc55cSDimitry Andric       reglist.push_back(Rz);
1400349cc55cSDimitry Andric 
1401349cc55cSDimitry Andric       if (getLexer().is(AsmToken::Comma))
1402349cc55cSDimitry Andric         getLexer().Lex(); // eat ','
1403349cc55cSDimitry Andric       else if (getLexer().is(AsmToken::EndOfStatement))
1404349cc55cSDimitry Andric         break;
1405349cc55cSDimitry Andric 
1406349cc55cSDimitry Andric     } else if (getLexer().is(AsmToken::Comma)) {
1407349cc55cSDimitry Andric       reglist.push_back(Ry);
1408349cc55cSDimitry Andric       reglist.push_back(Ry);
1409349cc55cSDimitry Andric 
1410349cc55cSDimitry Andric       getLexer().Lex(); // eat ','
1411349cc55cSDimitry Andric     } else if (getLexer().is(AsmToken::EndOfStatement)) {
1412349cc55cSDimitry Andric       reglist.push_back(Ry);
1413349cc55cSDimitry Andric       reglist.push_back(Ry);
1414349cc55cSDimitry Andric       break;
1415349cc55cSDimitry Andric     } else {
1416349cc55cSDimitry Andric       Error(getLoc(), "invalid register list");
1417349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1418349cc55cSDimitry Andric     }
1419349cc55cSDimitry Andric   }
1420349cc55cSDimitry Andric 
1421349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createRegList(reglist, S));
1422fe6060f1SDimitry Andric   return MatchOperand_Success;
1423fe6060f1SDimitry Andric }
1424fe6060f1SDimitry Andric 
1425fe6060f1SDimitry Andric bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1426fe6060f1SDimitry Andric                                      SMLoc NameLoc, OperandVector &Operands) {
1427fe6060f1SDimitry Andric   // First operand is token for instruction.
1428fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken(Name, NameLoc));
1429fe6060f1SDimitry Andric 
1430fe6060f1SDimitry Andric   // If there are no more operands, then finish.
1431fe6060f1SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement))
1432fe6060f1SDimitry Andric     return false;
1433fe6060f1SDimitry Andric 
1434fe6060f1SDimitry Andric   // Parse first operand.
1435fe6060f1SDimitry Andric   if (parseOperand(Operands, Name))
1436fe6060f1SDimitry Andric     return true;
1437fe6060f1SDimitry Andric 
1438fe6060f1SDimitry Andric   // Parse until end of statement, consuming commas between operands.
1439fe6060f1SDimitry Andric   while (getLexer().is(AsmToken::Comma)) {
1440fe6060f1SDimitry Andric     // Consume comma token.
1441fe6060f1SDimitry Andric     getLexer().Lex();
1442fe6060f1SDimitry Andric 
1443fe6060f1SDimitry Andric     // Parse next operand.
1444fe6060f1SDimitry Andric     if (parseOperand(Operands, Name))
1445fe6060f1SDimitry Andric       return true;
1446fe6060f1SDimitry Andric   }
1447fe6060f1SDimitry Andric 
1448fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1449fe6060f1SDimitry Andric     SMLoc Loc = getLexer().getLoc();
1450fe6060f1SDimitry Andric     getParser().eatToEndOfStatement();
1451fe6060f1SDimitry Andric     return Error(Loc, "unexpected token");
1452fe6060f1SDimitry Andric   }
1453fe6060f1SDimitry Andric 
1454fe6060f1SDimitry Andric   getParser().Lex(); // Consume the EndOfStatement.
1455fe6060f1SDimitry Andric   return false;
1456fe6060f1SDimitry Andric }
1457fe6060f1SDimitry Andric 
1458fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::tryParseRegister(unsigned &RegNo,
1459fe6060f1SDimitry Andric                                                      SMLoc &StartLoc,
1460fe6060f1SDimitry Andric                                                      SMLoc &EndLoc) {
1461fe6060f1SDimitry Andric   const AsmToken &Tok = getParser().getTok();
1462fe6060f1SDimitry Andric   StartLoc = Tok.getLoc();
1463fe6060f1SDimitry Andric   EndLoc = Tok.getEndLoc();
1464fe6060f1SDimitry Andric 
1465fe6060f1SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
1466fe6060f1SDimitry Andric 
1467349cc55cSDimitry Andric   if (matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name))
1468fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1469fe6060f1SDimitry Andric 
1470fe6060f1SDimitry Andric   getParser().Lex(); // Eat identifier token.
1471fe6060f1SDimitry Andric   return MatchOperand_Success;
1472fe6060f1SDimitry Andric }
1473fe6060f1SDimitry Andric 
1474fe6060f1SDimitry Andric bool CSKYAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
1475fe6060f1SDimitry Andric 
14760eae32dcSDimitry Andric void CSKYAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
14770eae32dcSDimitry Andric   MCInst CInst;
14780eae32dcSDimitry Andric   bool Res = false;
14790eae32dcSDimitry Andric   if (EnableCompressedInst)
14800eae32dcSDimitry Andric     Res = compressInst(CInst, Inst, getSTI(), S.getContext());
14810eae32dcSDimitry Andric   if (Res)
14820eae32dcSDimitry Andric     ++CSKYNumInstrsCompressed;
14830eae32dcSDimitry Andric   S.emitInstruction((Res ? CInst : Inst), getSTI());
14840eae32dcSDimitry Andric }
14850eae32dcSDimitry Andric 
1486fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser() {
1487fe6060f1SDimitry Andric   RegisterMCAsmParser<CSKYAsmParser> X(getTheCSKYTarget());
1488fe6060f1SDimitry Andric }
1489