xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
1281ad6265SDimitry Andric #include "MCTargetDesc/CSKYTargetStreamer.h"
13fe6060f1SDimitry Andric #include "TargetInfo/CSKYTargetInfo.h"
14fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h"
150eae32dcSDimitry Andric #include "llvm/ADT/Statistic.h"
16fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
1781ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
18fe6060f1SDimitry Andric #include "llvm/CodeGen/Register.h"
19fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h"
20fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h"
21fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h"
2281ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
23fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
24fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
25fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
26fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
27349cc55cSDimitry Andric #include "llvm/MC/MCSectionELF.h"
28fe6060f1SDimitry Andric #include "llvm/MC/MCStreamer.h"
29fe6060f1SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
30349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
3181ad6265SDimitry Andric #include "llvm/Support/CSKYAttributes.h"
3281ad6265SDimitry Andric #include "llvm/Support/CSKYTargetParser.h"
33fe6060f1SDimitry Andric #include "llvm/Support/Casting.h"
340eae32dcSDimitry Andric #include "llvm/Support/CommandLine.h"
35349cc55cSDimitry Andric #include "llvm/Support/Debug.h"
36349cc55cSDimitry Andric 
370eae32dcSDimitry Andric using namespace llvm;
380eae32dcSDimitry Andric 
39349cc55cSDimitry Andric #define DEBUG_TYPE "csky-asm-parser"
40fe6060f1SDimitry Andric 
410eae32dcSDimitry Andric // Include the auto-generated portion of the compress emitter.
420eae32dcSDimitry Andric #define GEN_COMPRESS_INSTR
430eae32dcSDimitry Andric #include "CSKYGenCompressInstEmitter.inc"
440eae32dcSDimitry Andric 
450eae32dcSDimitry Andric STATISTIC(CSKYNumInstrsCompressed,
460eae32dcSDimitry Andric           "Number of C-SKY Compressed instructions emitted");
470eae32dcSDimitry Andric 
480eae32dcSDimitry Andric static cl::opt<bool>
490eae32dcSDimitry Andric     EnableCompressedInst("enable-csky-asm-compressed-inst", cl::Hidden,
500eae32dcSDimitry Andric                          cl::init(false),
510eae32dcSDimitry Andric                          cl::desc("Enable C-SKY asm compressed instruction"));
52fe6060f1SDimitry Andric 
53fe6060f1SDimitry Andric namespace {
54fe6060f1SDimitry Andric struct CSKYOperand;
55fe6060f1SDimitry Andric 
56fe6060f1SDimitry Andric class CSKYAsmParser : public MCTargetAsmParser {
57fe6060f1SDimitry Andric 
58349cc55cSDimitry Andric   const MCRegisterInfo *MRI;
59349cc55cSDimitry Andric 
6081ad6265SDimitry Andric   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
6181ad6265SDimitry Andric                                       unsigned Kind) override;
6281ad6265SDimitry Andric 
63fe6060f1SDimitry Andric   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
64fe6060f1SDimitry Andric                                   int64_t Lower, int64_t Upper, Twine Msg);
65fe6060f1SDimitry Andric 
66fe6060f1SDimitry Andric   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
67fe6060f1SDimitry Andric 
68fe6060f1SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
69fe6060f1SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
70fe6060f1SDimitry Andric                                uint64_t &ErrorInfo,
71fe6060f1SDimitry Andric                                bool MatchingInlineAsm) override;
72fe6060f1SDimitry Andric 
73*bdd1243dSDimitry Andric   bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
74*bdd1243dSDimitry Andric                      SMLoc &EndLoc) override;
75fe6060f1SDimitry Andric 
76fe6060f1SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
77fe6060f1SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
78fe6060f1SDimitry Andric 
79fe6060f1SDimitry Andric   bool ParseDirective(AsmToken DirectiveID) override;
80fe6060f1SDimitry Andric 
810eae32dcSDimitry Andric   // Helper to actually emit an instruction to the MCStreamer. Also, when
820eae32dcSDimitry Andric   // possible, compression of the instruction is performed.
830eae32dcSDimitry Andric   void emitToStreamer(MCStreamer &S, const MCInst &Inst);
840eae32dcSDimitry Andric 
85*bdd1243dSDimitry Andric   OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
86fe6060f1SDimitry Andric                                         SMLoc &EndLoc) override;
87fe6060f1SDimitry Andric 
88349cc55cSDimitry Andric   bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
89349cc55cSDimitry Andric                           MCStreamer &Out);
9081ad6265SDimitry Andric   bool processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
9181ad6265SDimitry Andric   bool processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
9281ad6265SDimitry Andric   bool processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
9381ad6265SDimitry Andric 
9481ad6265SDimitry Andric   CSKYTargetStreamer &getTargetStreamer() {
9581ad6265SDimitry Andric     assert(getParser().getStreamer().getTargetStreamer() &&
9681ad6265SDimitry Andric            "do not have a target streamer");
9781ad6265SDimitry Andric     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
9881ad6265SDimitry Andric     return static_cast<CSKYTargetStreamer &>(TS);
9981ad6265SDimitry Andric   }
100349cc55cSDimitry Andric 
101fe6060f1SDimitry Andric // Auto-generated instruction matching functions
102fe6060f1SDimitry Andric #define GET_ASSEMBLER_HEADER
103fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
104fe6060f1SDimitry Andric 
105fe6060f1SDimitry Andric   OperandMatchResultTy parseImmediate(OperandVector &Operands);
106fe6060f1SDimitry Andric   OperandMatchResultTy parseRegister(OperandVector &Operands);
107fe6060f1SDimitry Andric   OperandMatchResultTy parseBaseRegImm(OperandVector &Operands);
108fe6060f1SDimitry Andric   OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands);
109fe6060f1SDimitry Andric   OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands);
110349cc55cSDimitry Andric   OperandMatchResultTy parseDataSymbol(OperandVector &Operands);
111349cc55cSDimitry Andric   OperandMatchResultTy parsePSRFlag(OperandVector &Operands);
112349cc55cSDimitry Andric   OperandMatchResultTy parseRegSeq(OperandVector &Operands);
113349cc55cSDimitry Andric   OperandMatchResultTy parseRegList(OperandVector &Operands);
114fe6060f1SDimitry Andric 
115fe6060f1SDimitry Andric   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
116fe6060f1SDimitry Andric 
11781ad6265SDimitry Andric   bool parseDirectiveAttribute();
11881ad6265SDimitry Andric 
119fe6060f1SDimitry Andric public:
120fe6060f1SDimitry Andric   enum CSKYMatchResultTy {
121fe6060f1SDimitry Andric     Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
122349cc55cSDimitry Andric     Match_RequiresSameSrcAndDst,
123349cc55cSDimitry Andric     Match_InvalidRegOutOfRange,
124fe6060f1SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
125fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
126fe6060f1SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES
127fe6060f1SDimitry Andric   };
128fe6060f1SDimitry Andric 
129fe6060f1SDimitry Andric   CSKYAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
130fe6060f1SDimitry Andric                 const MCInstrInfo &MII, const MCTargetOptions &Options)
131fe6060f1SDimitry Andric       : MCTargetAsmParser(Options, STI, MII) {
13281ad6265SDimitry Andric 
13381ad6265SDimitry Andric     MCAsmParserExtension::Initialize(Parser);
13481ad6265SDimitry Andric 
13581ad6265SDimitry Andric     // Cache the MCRegisterInfo.
13681ad6265SDimitry Andric     MRI = getContext().getRegisterInfo();
13781ad6265SDimitry Andric 
138fe6060f1SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
13981ad6265SDimitry Andric     getTargetStreamer().emitTargetAttributes(STI);
140fe6060f1SDimitry Andric   }
141fe6060f1SDimitry Andric };
142fe6060f1SDimitry Andric 
143fe6060f1SDimitry Andric /// Instances of this class represent a parsed machine instruction.
144fe6060f1SDimitry Andric struct CSKYOperand : public MCParsedAsmOperand {
145349cc55cSDimitry Andric 
146fe6060f1SDimitry Andric   enum KindTy {
147fe6060f1SDimitry Andric     Token,
148fe6060f1SDimitry Andric     Register,
149fe6060f1SDimitry Andric     Immediate,
150349cc55cSDimitry Andric     RegisterSeq,
151349cc55cSDimitry Andric     CPOP,
152349cc55cSDimitry Andric     RegisterList
153fe6060f1SDimitry Andric   } Kind;
154fe6060f1SDimitry Andric 
155fe6060f1SDimitry Andric   struct RegOp {
156fe6060f1SDimitry Andric     unsigned RegNum;
157fe6060f1SDimitry Andric   };
158fe6060f1SDimitry Andric 
159fe6060f1SDimitry Andric   struct ImmOp {
160fe6060f1SDimitry Andric     const MCExpr *Val;
161fe6060f1SDimitry Andric   };
162fe6060f1SDimitry Andric 
163349cc55cSDimitry Andric   struct ConstpoolOp {
164349cc55cSDimitry Andric     const MCExpr *Val;
165349cc55cSDimitry Andric   };
166349cc55cSDimitry Andric 
167349cc55cSDimitry Andric   struct RegSeqOp {
168349cc55cSDimitry Andric     unsigned RegNumFrom;
169349cc55cSDimitry Andric     unsigned RegNumTo;
170349cc55cSDimitry Andric   };
171349cc55cSDimitry Andric 
172349cc55cSDimitry Andric   struct RegListOp {
173349cc55cSDimitry Andric     unsigned List1From = 0;
174349cc55cSDimitry Andric     unsigned List1To = 0;
175349cc55cSDimitry Andric     unsigned List2From = 0;
176349cc55cSDimitry Andric     unsigned List2To = 0;
177349cc55cSDimitry Andric     unsigned List3From = 0;
178349cc55cSDimitry Andric     unsigned List3To = 0;
179349cc55cSDimitry Andric     unsigned List4From = 0;
180349cc55cSDimitry Andric     unsigned List4To = 0;
181349cc55cSDimitry Andric   };
182349cc55cSDimitry Andric 
183fe6060f1SDimitry Andric   SMLoc StartLoc, EndLoc;
184fe6060f1SDimitry Andric   union {
185fe6060f1SDimitry Andric     StringRef Tok;
186fe6060f1SDimitry Andric     RegOp Reg;
187fe6060f1SDimitry Andric     ImmOp Imm;
188349cc55cSDimitry Andric     ConstpoolOp CPool;
189349cc55cSDimitry Andric     RegSeqOp RegSeq;
190349cc55cSDimitry Andric     RegListOp RegList;
191fe6060f1SDimitry Andric   };
192fe6060f1SDimitry Andric 
193fe6060f1SDimitry Andric   CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
194fe6060f1SDimitry Andric 
195fe6060f1SDimitry Andric public:
196fe6060f1SDimitry Andric   CSKYOperand(const CSKYOperand &o) : MCParsedAsmOperand() {
197fe6060f1SDimitry Andric     Kind = o.Kind;
198fe6060f1SDimitry Andric     StartLoc = o.StartLoc;
199fe6060f1SDimitry Andric     EndLoc = o.EndLoc;
200fe6060f1SDimitry Andric     switch (Kind) {
201fe6060f1SDimitry Andric     case Register:
202fe6060f1SDimitry Andric       Reg = o.Reg;
203fe6060f1SDimitry Andric       break;
204349cc55cSDimitry Andric     case RegisterSeq:
205349cc55cSDimitry Andric       RegSeq = o.RegSeq;
206349cc55cSDimitry Andric       break;
207349cc55cSDimitry Andric     case CPOP:
208349cc55cSDimitry Andric       CPool = o.CPool;
209349cc55cSDimitry Andric       break;
210fe6060f1SDimitry Andric     case Immediate:
211fe6060f1SDimitry Andric       Imm = o.Imm;
212fe6060f1SDimitry Andric       break;
213fe6060f1SDimitry Andric     case Token:
214fe6060f1SDimitry Andric       Tok = o.Tok;
215fe6060f1SDimitry Andric       break;
216349cc55cSDimitry Andric     case RegisterList:
217349cc55cSDimitry Andric       RegList = o.RegList;
218349cc55cSDimitry Andric       break;
219fe6060f1SDimitry Andric     }
220fe6060f1SDimitry Andric   }
221fe6060f1SDimitry Andric 
222fe6060f1SDimitry Andric   bool isToken() const override { return Kind == Token; }
223fe6060f1SDimitry Andric   bool isReg() const override { return Kind == Register; }
224fe6060f1SDimitry Andric   bool isImm() const override { return Kind == Immediate; }
225349cc55cSDimitry Andric   bool isRegisterSeq() const { return Kind == RegisterSeq; }
226349cc55cSDimitry Andric   bool isRegisterList() const { return Kind == RegisterList; }
227349cc55cSDimitry Andric   bool isConstPoolOp() const { return Kind == CPOP; }
228349cc55cSDimitry Andric 
229fe6060f1SDimitry Andric   bool isMem() const override { return false; }
230fe6060f1SDimitry Andric 
231fe6060f1SDimitry Andric   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
232fe6060f1SDimitry Andric     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
233fe6060f1SDimitry Andric       Imm = CE->getValue();
234fe6060f1SDimitry Andric       return true;
235fe6060f1SDimitry Andric     }
236fe6060f1SDimitry Andric 
237fe6060f1SDimitry Andric     return false;
238fe6060f1SDimitry Andric   }
239fe6060f1SDimitry Andric 
240fe6060f1SDimitry Andric   template <unsigned num, unsigned shift = 0> bool isUImm() const {
241fe6060f1SDimitry Andric     if (!isImm())
242fe6060f1SDimitry Andric       return false;
243fe6060f1SDimitry Andric 
244fe6060f1SDimitry Andric     int64_t Imm;
245fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
246fe6060f1SDimitry Andric     return IsConstantImm && isShiftedUInt<num, shift>(Imm);
247fe6060f1SDimitry Andric   }
248fe6060f1SDimitry Andric 
249fe6060f1SDimitry Andric   template <unsigned num> bool isOImm() const {
250fe6060f1SDimitry Andric     if (!isImm())
251fe6060f1SDimitry Andric       return false;
252fe6060f1SDimitry Andric 
253fe6060f1SDimitry Andric     int64_t Imm;
254fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
255fe6060f1SDimitry Andric     return IsConstantImm && isUInt<num>(Imm - 1);
256fe6060f1SDimitry Andric   }
257fe6060f1SDimitry Andric 
258fe6060f1SDimitry Andric   template <unsigned num, unsigned shift = 0> bool isSImm() const {
259fe6060f1SDimitry Andric     if (!isImm())
260fe6060f1SDimitry Andric       return false;
261fe6060f1SDimitry Andric 
262fe6060f1SDimitry Andric     int64_t Imm;
263fe6060f1SDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
264fe6060f1SDimitry Andric     return IsConstantImm && isShiftedInt<num, shift>(Imm);
265fe6060f1SDimitry Andric   }
266fe6060f1SDimitry Andric 
267349cc55cSDimitry Andric   bool isUImm1() const { return isUImm<1>(); }
268fe6060f1SDimitry Andric   bool isUImm2() const { return isUImm<2>(); }
269349cc55cSDimitry Andric   bool isUImm3() const { return isUImm<3>(); }
270349cc55cSDimitry Andric   bool isUImm4() const { return isUImm<4>(); }
271fe6060f1SDimitry Andric   bool isUImm5() const { return isUImm<5>(); }
272349cc55cSDimitry Andric   bool isUImm6() const { return isUImm<6>(); }
273349cc55cSDimitry Andric   bool isUImm7() const { return isUImm<7>(); }
274349cc55cSDimitry Andric   bool isUImm8() const { return isUImm<8>(); }
275fe6060f1SDimitry Andric   bool isUImm12() const { return isUImm<12>(); }
276fe6060f1SDimitry Andric   bool isUImm16() const { return isUImm<16>(); }
277349cc55cSDimitry Andric   bool isUImm20() const { return isUImm<20>(); }
278349cc55cSDimitry Andric   bool isUImm24() const { return isUImm<24>(); }
279fe6060f1SDimitry Andric 
280349cc55cSDimitry Andric   bool isOImm3() const { return isOImm<3>(); }
281349cc55cSDimitry Andric   bool isOImm4() const { return isOImm<4>(); }
282349cc55cSDimitry Andric   bool isOImm5() const { return isOImm<5>(); }
283349cc55cSDimitry Andric   bool isOImm6() const { return isOImm<6>(); }
284349cc55cSDimitry Andric   bool isOImm8() const { return isOImm<8>(); }
285fe6060f1SDimitry Andric   bool isOImm12() const { return isOImm<12>(); }
286fe6060f1SDimitry Andric   bool isOImm16() const { return isOImm<16>(); }
287fe6060f1SDimitry Andric 
288349cc55cSDimitry Andric   bool isSImm8() const { return isSImm<8>(); }
289349cc55cSDimitry Andric 
290349cc55cSDimitry Andric   bool isUImm5Shift1() { return isUImm<5, 1>(); }
291349cc55cSDimitry Andric   bool isUImm5Shift2() { return isUImm<5, 2>(); }
292349cc55cSDimitry Andric   bool isUImm7Shift1() { return isUImm<7, 1>(); }
293349cc55cSDimitry Andric   bool isUImm7Shift2() { return isUImm<7, 2>(); }
294349cc55cSDimitry Andric   bool isUImm7Shift3() { return isUImm<7, 3>(); }
295349cc55cSDimitry Andric   bool isUImm8Shift2() { return isUImm<8, 2>(); }
296349cc55cSDimitry Andric   bool isUImm8Shift3() { return isUImm<8, 3>(); }
297349cc55cSDimitry Andric   bool isUImm8Shift8() { return isUImm<8, 8>(); }
298349cc55cSDimitry Andric   bool isUImm8Shift16() { return isUImm<8, 16>(); }
299349cc55cSDimitry Andric   bool isUImm8Shift24() { return isUImm<8, 24>(); }
300fe6060f1SDimitry Andric   bool isUImm12Shift1() { return isUImm<12, 1>(); }
301fe6060f1SDimitry Andric   bool isUImm12Shift2() { return isUImm<12, 2>(); }
302349cc55cSDimitry Andric   bool isUImm16Shift8() { return isUImm<16, 8>(); }
303349cc55cSDimitry Andric   bool isUImm16Shift16() { return isUImm<16, 16>(); }
304349cc55cSDimitry Andric   bool isUImm24Shift8() { return isUImm<24, 8>(); }
305fe6060f1SDimitry Andric 
306fe6060f1SDimitry Andric   bool isSImm16Shift1() { return isSImm<16, 1>(); }
307fe6060f1SDimitry Andric 
308349cc55cSDimitry Andric   bool isCSKYSymbol() const { return isImm(); }
309349cc55cSDimitry Andric 
310349cc55cSDimitry Andric   bool isConstpool() const { return isConstPoolOp(); }
311349cc55cSDimitry Andric   bool isDataSymbol() const { return isConstPoolOp(); }
312349cc55cSDimitry Andric 
313349cc55cSDimitry Andric   bool isPSRFlag() const {
314fe6060f1SDimitry Andric     int64_t Imm;
315349cc55cSDimitry Andric     // Must be of 'immediate' type and a constant.
316349cc55cSDimitry Andric     if (!isImm() || !evaluateConstantImm(getImm(), Imm))
317349cc55cSDimitry Andric       return false;
318349cc55cSDimitry Andric 
319349cc55cSDimitry Andric     return isUInt<5>(Imm);
320349cc55cSDimitry Andric   }
321349cc55cSDimitry Andric 
322349cc55cSDimitry Andric   template <unsigned MIN, unsigned MAX> bool isRegSeqTemplate() const {
323349cc55cSDimitry Andric     if (!isRegisterSeq())
324349cc55cSDimitry Andric       return false;
325349cc55cSDimitry Andric 
326349cc55cSDimitry Andric     std::pair<unsigned, unsigned> regSeq = getRegSeq();
327349cc55cSDimitry Andric 
328349cc55cSDimitry Andric     return MIN <= regSeq.first && regSeq.first <= regSeq.second &&
329349cc55cSDimitry Andric            regSeq.second <= MAX;
330349cc55cSDimitry Andric   }
331349cc55cSDimitry Andric 
332349cc55cSDimitry Andric   bool isRegSeq() const { return isRegSeqTemplate<CSKY::R0, CSKY::R31>(); }
333349cc55cSDimitry Andric 
33404eeddc0SDimitry Andric   bool isRegSeqV1() const {
33504eeddc0SDimitry Andric     return isRegSeqTemplate<CSKY::F0_32, CSKY::F15_32>();
33604eeddc0SDimitry Andric   }
33704eeddc0SDimitry Andric 
33804eeddc0SDimitry Andric   bool isRegSeqV2() const {
33904eeddc0SDimitry Andric     return isRegSeqTemplate<CSKY::F0_32, CSKY::F31_32>();
34004eeddc0SDimitry Andric   }
34104eeddc0SDimitry Andric 
342349cc55cSDimitry Andric   static bool isLegalRegList(unsigned from, unsigned to) {
343349cc55cSDimitry Andric     if (from == 0 && to == 0)
344349cc55cSDimitry Andric       return true;
345349cc55cSDimitry Andric 
346349cc55cSDimitry Andric     if (from == to) {
347349cc55cSDimitry Andric       if (from != CSKY::R4 && from != CSKY::R15 && from != CSKY::R16 &&
348349cc55cSDimitry Andric           from != CSKY::R28)
349349cc55cSDimitry Andric         return false;
350349cc55cSDimitry Andric 
351349cc55cSDimitry Andric       return true;
352349cc55cSDimitry Andric     } else {
353349cc55cSDimitry Andric       if (from != CSKY::R4 && from != CSKY::R16)
354349cc55cSDimitry Andric         return false;
355349cc55cSDimitry Andric 
356349cc55cSDimitry Andric       if (from == CSKY::R4 && to > CSKY::R4 && to < CSKY::R12)
357349cc55cSDimitry Andric         return true;
358349cc55cSDimitry Andric       else if (from == CSKY::R16 && to > CSKY::R16 && to < CSKY::R18)
359349cc55cSDimitry Andric         return true;
360349cc55cSDimitry Andric       else
361349cc55cSDimitry Andric         return false;
362349cc55cSDimitry Andric     }
363349cc55cSDimitry Andric   }
364349cc55cSDimitry Andric 
365349cc55cSDimitry Andric   bool isRegList() const {
366349cc55cSDimitry Andric     if (!isRegisterList())
367349cc55cSDimitry Andric       return false;
368349cc55cSDimitry Andric 
369349cc55cSDimitry Andric     auto regList = getRegList();
370349cc55cSDimitry Andric 
371349cc55cSDimitry Andric     if (!isLegalRegList(regList.List1From, regList.List1To))
372349cc55cSDimitry Andric       return false;
373349cc55cSDimitry Andric     if (!isLegalRegList(regList.List2From, regList.List2To))
374349cc55cSDimitry Andric       return false;
375349cc55cSDimitry Andric     if (!isLegalRegList(regList.List3From, regList.List3To))
376349cc55cSDimitry Andric       return false;
377349cc55cSDimitry Andric     if (!isLegalRegList(regList.List4From, regList.List4To))
378349cc55cSDimitry Andric       return false;
379349cc55cSDimitry Andric 
380349cc55cSDimitry Andric     return true;
381349cc55cSDimitry Andric   }
382349cc55cSDimitry Andric 
383349cc55cSDimitry Andric   bool isExtImm6() {
384349cc55cSDimitry Andric     if (!isImm())
385349cc55cSDimitry Andric       return false;
386349cc55cSDimitry Andric 
387349cc55cSDimitry Andric     int64_t Imm;
388349cc55cSDimitry Andric     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
389349cc55cSDimitry Andric     if (!IsConstantImm)
390349cc55cSDimitry Andric       return false;
391349cc55cSDimitry Andric 
392349cc55cSDimitry Andric     int uimm4 = Imm & 0xf;
393349cc55cSDimitry Andric 
394349cc55cSDimitry Andric     return isShiftedUInt<6, 0>(Imm) && uimm4 >= 0 && uimm4 <= 14;
395fe6060f1SDimitry Andric   }
396fe6060f1SDimitry Andric 
397fe6060f1SDimitry Andric   /// Gets location of the first token of this operand.
398fe6060f1SDimitry Andric   SMLoc getStartLoc() const override { return StartLoc; }
399fe6060f1SDimitry Andric   /// Gets location of the last token of this operand.
400fe6060f1SDimitry Andric   SMLoc getEndLoc() const override { return EndLoc; }
401fe6060f1SDimitry Andric 
402fe6060f1SDimitry Andric   unsigned getReg() const override {
403fe6060f1SDimitry Andric     assert(Kind == Register && "Invalid type access!");
404fe6060f1SDimitry Andric     return Reg.RegNum;
405fe6060f1SDimitry Andric   }
406fe6060f1SDimitry Andric 
407349cc55cSDimitry Andric   std::pair<unsigned, unsigned> getRegSeq() const {
408349cc55cSDimitry Andric     assert(Kind == RegisterSeq && "Invalid type access!");
409349cc55cSDimitry Andric     return std::pair<unsigned, unsigned>(RegSeq.RegNumFrom, RegSeq.RegNumTo);
410349cc55cSDimitry Andric   }
411349cc55cSDimitry Andric 
412349cc55cSDimitry Andric   RegListOp getRegList() const {
413349cc55cSDimitry Andric     assert(Kind == RegisterList && "Invalid type access!");
414349cc55cSDimitry Andric     return RegList;
415349cc55cSDimitry Andric   }
416349cc55cSDimitry Andric 
417fe6060f1SDimitry Andric   const MCExpr *getImm() const {
418fe6060f1SDimitry Andric     assert(Kind == Immediate && "Invalid type access!");
419fe6060f1SDimitry Andric     return Imm.Val;
420fe6060f1SDimitry Andric   }
421fe6060f1SDimitry Andric 
422349cc55cSDimitry Andric   const MCExpr *getConstpoolOp() const {
423349cc55cSDimitry Andric     assert(Kind == CPOP && "Invalid type access!");
424349cc55cSDimitry Andric     return CPool.Val;
425349cc55cSDimitry Andric   }
426349cc55cSDimitry Andric 
427fe6060f1SDimitry Andric   StringRef getToken() const {
428fe6060f1SDimitry Andric     assert(Kind == Token && "Invalid type access!");
429fe6060f1SDimitry Andric     return Tok;
430fe6060f1SDimitry Andric   }
431fe6060f1SDimitry Andric 
432fe6060f1SDimitry Andric   void print(raw_ostream &OS) const override {
433*bdd1243dSDimitry Andric     auto RegName = [](MCRegister Reg) {
434349cc55cSDimitry Andric       if (Reg)
435349cc55cSDimitry Andric         return CSKYInstPrinter::getRegisterName(Reg);
436349cc55cSDimitry Andric       else
437349cc55cSDimitry Andric         return "noreg";
438349cc55cSDimitry Andric     };
439349cc55cSDimitry Andric 
440fe6060f1SDimitry Andric     switch (Kind) {
441349cc55cSDimitry Andric     case CPOP:
442349cc55cSDimitry Andric       OS << *getConstpoolOp();
443349cc55cSDimitry Andric       break;
444fe6060f1SDimitry Andric     case Immediate:
445fe6060f1SDimitry Andric       OS << *getImm();
446fe6060f1SDimitry Andric       break;
447349cc55cSDimitry Andric     case KindTy::Register:
448349cc55cSDimitry Andric       OS << "<register " << RegName(getReg()) << ">";
449349cc55cSDimitry Andric       break;
450349cc55cSDimitry Andric     case RegisterSeq:
451349cc55cSDimitry Andric       OS << "<register-seq ";
452349cc55cSDimitry Andric       OS << RegName(getRegSeq().first) << "-" << RegName(getRegSeq().second)
453349cc55cSDimitry Andric          << ">";
454349cc55cSDimitry Andric       break;
455349cc55cSDimitry Andric     case RegisterList:
456349cc55cSDimitry Andric       OS << "<register-list ";
457349cc55cSDimitry Andric       OS << RegName(getRegList().List1From) << "-"
458349cc55cSDimitry Andric          << RegName(getRegList().List1To) << ",";
459349cc55cSDimitry Andric       OS << RegName(getRegList().List2From) << "-"
460349cc55cSDimitry Andric          << RegName(getRegList().List2To) << ",";
461349cc55cSDimitry Andric       OS << RegName(getRegList().List3From) << "-"
462349cc55cSDimitry Andric          << RegName(getRegList().List3To) << ",";
463349cc55cSDimitry Andric       OS << RegName(getRegList().List4From) << "-"
464349cc55cSDimitry Andric          << RegName(getRegList().List4To);
465fe6060f1SDimitry Andric       break;
466fe6060f1SDimitry Andric     case Token:
467fe6060f1SDimitry Andric       OS << "'" << getToken() << "'";
468fe6060f1SDimitry Andric       break;
469fe6060f1SDimitry Andric     }
470fe6060f1SDimitry Andric   }
471fe6060f1SDimitry Andric 
472fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createToken(StringRef Str, SMLoc S) {
473fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Token);
474fe6060f1SDimitry Andric     Op->Tok = Str;
475fe6060f1SDimitry Andric     Op->StartLoc = S;
476fe6060f1SDimitry Andric     Op->EndLoc = S;
477fe6060f1SDimitry Andric     return Op;
478fe6060f1SDimitry Andric   }
479fe6060f1SDimitry Andric 
480fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createReg(unsigned RegNo, SMLoc S,
481fe6060f1SDimitry Andric                                                 SMLoc E) {
482fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Register);
483fe6060f1SDimitry Andric     Op->Reg.RegNum = RegNo;
484fe6060f1SDimitry Andric     Op->StartLoc = S;
485fe6060f1SDimitry Andric     Op->EndLoc = E;
486fe6060f1SDimitry Andric     return Op;
487fe6060f1SDimitry Andric   }
488fe6060f1SDimitry Andric 
489349cc55cSDimitry Andric   static std::unique_ptr<CSKYOperand> createRegSeq(unsigned RegNoFrom,
490349cc55cSDimitry Andric                                                    unsigned RegNoTo, SMLoc S) {
491349cc55cSDimitry Andric     auto Op = std::make_unique<CSKYOperand>(RegisterSeq);
492349cc55cSDimitry Andric     Op->RegSeq.RegNumFrom = RegNoFrom;
493349cc55cSDimitry Andric     Op->RegSeq.RegNumTo = RegNoTo;
494349cc55cSDimitry Andric     Op->StartLoc = S;
495349cc55cSDimitry Andric     Op->EndLoc = S;
496349cc55cSDimitry Andric     return Op;
497349cc55cSDimitry Andric   }
498349cc55cSDimitry Andric 
499349cc55cSDimitry Andric   static std::unique_ptr<CSKYOperand>
500349cc55cSDimitry Andric   createRegList(SmallVector<unsigned, 4> reglist, SMLoc S) {
501349cc55cSDimitry Andric     auto Op = std::make_unique<CSKYOperand>(RegisterList);
502349cc55cSDimitry Andric     Op->RegList.List1From = 0;
503349cc55cSDimitry Andric     Op->RegList.List1To = 0;
504349cc55cSDimitry Andric     Op->RegList.List2From = 0;
505349cc55cSDimitry Andric     Op->RegList.List2To = 0;
506349cc55cSDimitry Andric     Op->RegList.List3From = 0;
507349cc55cSDimitry Andric     Op->RegList.List3To = 0;
508349cc55cSDimitry Andric     Op->RegList.List4From = 0;
509349cc55cSDimitry Andric     Op->RegList.List4To = 0;
510349cc55cSDimitry Andric 
511349cc55cSDimitry Andric     for (unsigned i = 0; i < reglist.size(); i += 2) {
512349cc55cSDimitry Andric       if (Op->RegList.List1From == 0) {
513349cc55cSDimitry Andric         Op->RegList.List1From = reglist[i];
514349cc55cSDimitry Andric         Op->RegList.List1To = reglist[i + 1];
515349cc55cSDimitry Andric       } else if (Op->RegList.List2From == 0) {
516349cc55cSDimitry Andric         Op->RegList.List2From = reglist[i];
517349cc55cSDimitry Andric         Op->RegList.List2To = reglist[i + 1];
518349cc55cSDimitry Andric       } else if (Op->RegList.List3From == 0) {
519349cc55cSDimitry Andric         Op->RegList.List3From = reglist[i];
520349cc55cSDimitry Andric         Op->RegList.List3To = reglist[i + 1];
521349cc55cSDimitry Andric       } else if (Op->RegList.List4From == 0) {
522349cc55cSDimitry Andric         Op->RegList.List4From = reglist[i];
523349cc55cSDimitry Andric         Op->RegList.List4To = reglist[i + 1];
524349cc55cSDimitry Andric       } else {
525349cc55cSDimitry Andric         assert(0);
526349cc55cSDimitry Andric       }
527349cc55cSDimitry Andric     }
528349cc55cSDimitry Andric 
529349cc55cSDimitry Andric     Op->StartLoc = S;
530349cc55cSDimitry Andric     Op->EndLoc = S;
531349cc55cSDimitry Andric     return Op;
532349cc55cSDimitry Andric   }
533349cc55cSDimitry Andric 
534fe6060f1SDimitry Andric   static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S,
535fe6060f1SDimitry Andric                                                 SMLoc E) {
536fe6060f1SDimitry Andric     auto Op = std::make_unique<CSKYOperand>(Immediate);
537fe6060f1SDimitry Andric     Op->Imm.Val = Val;
538fe6060f1SDimitry Andric     Op->StartLoc = S;
539fe6060f1SDimitry Andric     Op->EndLoc = E;
540fe6060f1SDimitry Andric     return Op;
541fe6060f1SDimitry Andric   }
542fe6060f1SDimitry Andric 
543349cc55cSDimitry Andric   static std::unique_ptr<CSKYOperand> createConstpoolOp(const MCExpr *Val,
544349cc55cSDimitry Andric                                                         SMLoc S, SMLoc E) {
545349cc55cSDimitry Andric     auto Op = std::make_unique<CSKYOperand>(CPOP);
546349cc55cSDimitry Andric     Op->CPool.Val = Val;
547349cc55cSDimitry Andric     Op->StartLoc = S;
548349cc55cSDimitry Andric     Op->EndLoc = E;
549349cc55cSDimitry Andric     return Op;
550349cc55cSDimitry Andric   }
551349cc55cSDimitry Andric 
552fe6060f1SDimitry Andric   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
553fe6060f1SDimitry Andric     assert(Expr && "Expr shouldn't be null!");
554fe6060f1SDimitry Andric     if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
555fe6060f1SDimitry Andric       Inst.addOperand(MCOperand::createImm(CE->getValue()));
556fe6060f1SDimitry Andric     else
557fe6060f1SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
558fe6060f1SDimitry Andric   }
559fe6060f1SDimitry Andric 
560fe6060f1SDimitry Andric   // Used by the TableGen Code.
561fe6060f1SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
562fe6060f1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
563fe6060f1SDimitry Andric     Inst.addOperand(MCOperand::createReg(getReg()));
564fe6060f1SDimitry Andric   }
565fe6060f1SDimitry Andric 
566fe6060f1SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
567fe6060f1SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
568fe6060f1SDimitry Andric     addExpr(Inst, getImm());
569fe6060f1SDimitry Andric   }
570349cc55cSDimitry Andric 
571349cc55cSDimitry Andric   void addConstpoolOperands(MCInst &Inst, unsigned N) const {
572349cc55cSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
573349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createExpr(getConstpoolOp()));
574349cc55cSDimitry Andric   }
575349cc55cSDimitry Andric 
576349cc55cSDimitry Andric   void addRegSeqOperands(MCInst &Inst, unsigned N) const {
577349cc55cSDimitry Andric     assert(N == 2 && "Invalid number of operands!");
578349cc55cSDimitry Andric     auto regSeq = getRegSeq();
579349cc55cSDimitry Andric 
580349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createReg(regSeq.first));
581349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createReg(regSeq.second));
582349cc55cSDimitry Andric   }
583349cc55cSDimitry Andric 
584349cc55cSDimitry Andric   static unsigned getListValue(unsigned ListFrom, unsigned ListTo) {
585349cc55cSDimitry Andric     if (ListFrom == ListTo && ListFrom == CSKY::R15)
586349cc55cSDimitry Andric       return (1 << 4);
587349cc55cSDimitry Andric     else if (ListFrom == ListTo && ListFrom == CSKY::R28)
588349cc55cSDimitry Andric       return (1 << 8);
589349cc55cSDimitry Andric     else if (ListFrom == CSKY::R4)
590349cc55cSDimitry Andric       return ListTo - ListFrom + 1;
591349cc55cSDimitry Andric     else if (ListFrom == CSKY::R16)
592349cc55cSDimitry Andric       return ((ListTo - ListFrom + 1) << 5);
593349cc55cSDimitry Andric     else
594349cc55cSDimitry Andric       return 0;
595349cc55cSDimitry Andric   }
596349cc55cSDimitry Andric 
597349cc55cSDimitry Andric   void addRegListOperands(MCInst &Inst, unsigned N) const {
598349cc55cSDimitry Andric     assert(N == 1 && "Invalid number of operands!");
599349cc55cSDimitry Andric     auto regList = getRegList();
600349cc55cSDimitry Andric 
601349cc55cSDimitry Andric     unsigned V = 0;
602349cc55cSDimitry Andric 
603349cc55cSDimitry Andric     unsigned T = getListValue(regList.List1From, regList.List1To);
604349cc55cSDimitry Andric     if (T != 0)
605349cc55cSDimitry Andric       V = V | T;
606349cc55cSDimitry Andric 
607349cc55cSDimitry Andric     T = getListValue(regList.List2From, regList.List2To);
608349cc55cSDimitry Andric     if (T != 0)
609349cc55cSDimitry Andric       V = V | T;
610349cc55cSDimitry Andric 
611349cc55cSDimitry Andric     T = getListValue(regList.List3From, regList.List3To);
612349cc55cSDimitry Andric     if (T != 0)
613349cc55cSDimitry Andric       V = V | T;
614349cc55cSDimitry Andric 
615349cc55cSDimitry Andric     T = getListValue(regList.List4From, regList.List4To);
616349cc55cSDimitry Andric     if (T != 0)
617349cc55cSDimitry Andric       V = V | T;
618349cc55cSDimitry Andric 
619349cc55cSDimitry Andric     Inst.addOperand(MCOperand::createImm(V));
620349cc55cSDimitry Andric   }
621349cc55cSDimitry Andric 
622349cc55cSDimitry Andric   bool isValidForTie(const CSKYOperand &Other) const {
623349cc55cSDimitry Andric     if (Kind != Other.Kind)
624349cc55cSDimitry Andric       return false;
625349cc55cSDimitry Andric 
626349cc55cSDimitry Andric     switch (Kind) {
627349cc55cSDimitry Andric     default:
628349cc55cSDimitry Andric       llvm_unreachable("Unexpected kind");
629349cc55cSDimitry Andric       return false;
630349cc55cSDimitry Andric     case Register:
631349cc55cSDimitry Andric       return Reg.RegNum == Other.Reg.RegNum;
632349cc55cSDimitry Andric     }
633349cc55cSDimitry Andric   }
634fe6060f1SDimitry Andric };
635fe6060f1SDimitry Andric } // end anonymous namespace.
636fe6060f1SDimitry Andric 
637fe6060f1SDimitry Andric #define GET_REGISTER_MATCHER
638fe6060f1SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME
639fe6060f1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
640fe6060f1SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER
641fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc"
642fe6060f1SDimitry Andric 
64381ad6265SDimitry Andric static MCRegister convertFPR32ToFPR64(MCRegister Reg) {
64481ad6265SDimitry Andric   assert(Reg >= CSKY::F0_32 && Reg <= CSKY::F31_32 && "Invalid register");
64581ad6265SDimitry Andric   return Reg - CSKY::F0_32 + CSKY::F0_64;
64681ad6265SDimitry Andric }
64781ad6265SDimitry Andric 
648fe6060f1SDimitry Andric static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
649fe6060f1SDimitry Andric                                           unsigned VariantID = 0);
650fe6060f1SDimitry Andric 
651fe6060f1SDimitry Andric bool CSKYAsmParser::generateImmOutOfRangeError(
652fe6060f1SDimitry Andric     OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
653fe6060f1SDimitry Andric     Twine Msg = "immediate must be an integer in the range") {
654fe6060f1SDimitry Andric   SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
655fe6060f1SDimitry Andric   return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
656fe6060f1SDimitry Andric }
657fe6060f1SDimitry Andric 
658fe6060f1SDimitry Andric bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
659fe6060f1SDimitry Andric                                             OperandVector &Operands,
660fe6060f1SDimitry Andric                                             MCStreamer &Out,
661fe6060f1SDimitry Andric                                             uint64_t &ErrorInfo,
662fe6060f1SDimitry Andric                                             bool MatchingInlineAsm) {
663fe6060f1SDimitry Andric   MCInst Inst;
664fe6060f1SDimitry Andric   FeatureBitset MissingFeatures;
665fe6060f1SDimitry Andric 
666fe6060f1SDimitry Andric   auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
667fe6060f1SDimitry Andric                                      MatchingInlineAsm);
668fe6060f1SDimitry Andric   switch (Result) {
669fe6060f1SDimitry Andric   default:
670fe6060f1SDimitry Andric     break;
671fe6060f1SDimitry Andric   case Match_Success:
672349cc55cSDimitry Andric     return processInstruction(Inst, IDLoc, Operands, Out);
673fe6060f1SDimitry Andric   case Match_MissingFeature: {
674fe6060f1SDimitry Andric     assert(MissingFeatures.any() && "Unknown missing features!");
675fe6060f1SDimitry Andric     ListSeparator LS;
676fe6060f1SDimitry Andric     std::string Msg = "instruction requires the following: ";
677fe6060f1SDimitry Andric     for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
678fe6060f1SDimitry Andric       if (MissingFeatures[i]) {
679fe6060f1SDimitry Andric         Msg += LS;
680fe6060f1SDimitry Andric         Msg += getSubtargetFeatureName(i);
681fe6060f1SDimitry Andric       }
682fe6060f1SDimitry Andric     }
683fe6060f1SDimitry Andric     return Error(IDLoc, Msg);
684fe6060f1SDimitry Andric   }
685fe6060f1SDimitry Andric   case Match_MnemonicFail: {
686fe6060f1SDimitry Andric     FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
687fe6060f1SDimitry Andric     std::string Suggestion =
688fe6060f1SDimitry Andric         CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS);
689fe6060f1SDimitry Andric     return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
690fe6060f1SDimitry Andric   }
691fe6060f1SDimitry Andric   case Match_InvalidTiedOperand:
692fe6060f1SDimitry Andric   case Match_InvalidOperand: {
693fe6060f1SDimitry Andric     SMLoc ErrorLoc = IDLoc;
694fe6060f1SDimitry Andric     if (ErrorInfo != ~0U) {
695fe6060f1SDimitry Andric       if (ErrorInfo >= Operands.size())
696fe6060f1SDimitry Andric         return Error(ErrorLoc, "too few operands for instruction");
697fe6060f1SDimitry Andric 
698fe6060f1SDimitry Andric       ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
699fe6060f1SDimitry Andric       if (ErrorLoc == SMLoc())
700fe6060f1SDimitry Andric         ErrorLoc = IDLoc;
701fe6060f1SDimitry Andric     }
702fe6060f1SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
703fe6060f1SDimitry Andric   }
704fe6060f1SDimitry Andric   }
705fe6060f1SDimitry Andric 
706fe6060f1SDimitry Andric   // Handle the case when the error message is of specific type
707fe6060f1SDimitry Andric   // other than the generic Match_InvalidOperand, and the
708fe6060f1SDimitry Andric   // corresponding operand is missing.
709fe6060f1SDimitry Andric   if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
710fe6060f1SDimitry Andric     SMLoc ErrorLoc = IDLoc;
711fe6060f1SDimitry Andric     if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
712fe6060f1SDimitry Andric       return Error(ErrorLoc, "too few operands for instruction");
713fe6060f1SDimitry Andric   }
714fe6060f1SDimitry Andric 
715fe6060f1SDimitry Andric   switch (Result) {
716fe6060f1SDimitry Andric   default:
717fe6060f1SDimitry Andric     break;
718349cc55cSDimitry Andric   case Match_InvalidSImm8:
719349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 7),
720349cc55cSDimitry Andric                                       (1 << 7) - 1);
721349cc55cSDimitry Andric   case Match_InvalidOImm3:
722349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 3));
723349cc55cSDimitry Andric   case Match_InvalidOImm4:
724349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 4));
725349cc55cSDimitry Andric   case Match_InvalidOImm5:
726349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
727349cc55cSDimitry Andric   case Match_InvalidOImm6:
728349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6));
729349cc55cSDimitry Andric   case Match_InvalidOImm8:
730349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 8));
731fe6060f1SDimitry Andric   case Match_InvalidOImm12:
732fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12));
733fe6060f1SDimitry Andric   case Match_InvalidOImm16:
734fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16));
735349cc55cSDimitry Andric   case Match_InvalidUImm1:
736349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
737fe6060f1SDimitry Andric   case Match_InvalidUImm2:
738fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
739349cc55cSDimitry Andric   case Match_InvalidUImm3:
740349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
741349cc55cSDimitry Andric   case Match_InvalidUImm4:
742349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
743fe6060f1SDimitry Andric   case Match_InvalidUImm5:
744fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
745349cc55cSDimitry Andric   case Match_InvalidUImm6:
746349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
747349cc55cSDimitry Andric   case Match_InvalidUImm7:
748349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
749349cc55cSDimitry Andric   case Match_InvalidUImm8:
750349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
751fe6060f1SDimitry Andric   case Match_InvalidUImm12:
752fe6060f1SDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
753349cc55cSDimitry Andric   case Match_InvalidUImm16:
754349cc55cSDimitry Andric     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
755349cc55cSDimitry Andric   case Match_InvalidUImm5Shift1:
756349cc55cSDimitry Andric     return generateImmOutOfRangeError(
757349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 5) - 2,
758349cc55cSDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
759fe6060f1SDimitry Andric   case Match_InvalidUImm12Shift1:
760fe6060f1SDimitry Andric     return generateImmOutOfRangeError(
761fe6060f1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 12) - 2,
762fe6060f1SDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
763349cc55cSDimitry Andric   case Match_InvalidUImm5Shift2:
764349cc55cSDimitry Andric     return generateImmOutOfRangeError(
765349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 5) - 4,
766349cc55cSDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
767349cc55cSDimitry Andric   case Match_InvalidUImm7Shift1:
768349cc55cSDimitry Andric     return generateImmOutOfRangeError(
769349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 7) - 2,
770349cc55cSDimitry Andric         "immediate must be a multiple of 2 bytes in the range");
771349cc55cSDimitry Andric   case Match_InvalidUImm7Shift2:
772349cc55cSDimitry Andric     return generateImmOutOfRangeError(
773349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 7) - 4,
774349cc55cSDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
775349cc55cSDimitry Andric   case Match_InvalidUImm8Shift2:
776349cc55cSDimitry Andric     return generateImmOutOfRangeError(
777349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 4,
778349cc55cSDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
779349cc55cSDimitry Andric   case Match_InvalidUImm8Shift3:
780349cc55cSDimitry Andric     return generateImmOutOfRangeError(
781349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 8,
782349cc55cSDimitry Andric         "immediate must be a multiple of 8 bytes in the range");
783349cc55cSDimitry Andric   case Match_InvalidUImm8Shift8:
784349cc55cSDimitry Andric     return generateImmOutOfRangeError(
785349cc55cSDimitry Andric         Operands, ErrorInfo, 0, (1 << 8) - 256,
786349cc55cSDimitry Andric         "immediate must be a multiple of 256 bytes in the range");
787fe6060f1SDimitry Andric   case Match_InvalidUImm12Shift2:
788fe6060f1SDimitry Andric     return generateImmOutOfRangeError(
789fe6060f1SDimitry Andric         Operands, ErrorInfo, 0, (1 << 12) - 4,
790fe6060f1SDimitry Andric         "immediate must be a multiple of 4 bytes in the range");
791fe6060f1SDimitry Andric   case Match_InvalidCSKYSymbol: {
792fe6060f1SDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
793fe6060f1SDimitry Andric     return Error(ErrorLoc, "operand must be a symbol name");
794fe6060f1SDimitry Andric   }
795fe6060f1SDimitry Andric   case Match_InvalidConstpool: {
796fe6060f1SDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
797fe6060f1SDimitry Andric     return Error(ErrorLoc, "operand must be a constpool symbol name");
798fe6060f1SDimitry Andric   }
799349cc55cSDimitry Andric   case Match_InvalidPSRFlag: {
800349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
801349cc55cSDimitry Andric     return Error(ErrorLoc, "psrset operand is not valid");
802349cc55cSDimitry Andric   }
803349cc55cSDimitry Andric   case Match_InvalidRegSeq: {
804349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
805349cc55cSDimitry Andric     return Error(ErrorLoc, "Register sequence is not valid");
806349cc55cSDimitry Andric   }
807349cc55cSDimitry Andric   case Match_InvalidRegOutOfRange: {
808349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
809349cc55cSDimitry Andric     return Error(ErrorLoc, "register is out of range");
810349cc55cSDimitry Andric   }
811349cc55cSDimitry Andric   case Match_RequiresSameSrcAndDst: {
812349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
813349cc55cSDimitry Andric     return Error(ErrorLoc, "src and dst operand must be same");
814349cc55cSDimitry Andric   }
815349cc55cSDimitry Andric   case Match_InvalidRegList: {
816349cc55cSDimitry Andric     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
817349cc55cSDimitry Andric     return Error(ErrorLoc, "invalid register list");
818349cc55cSDimitry Andric   }
819349cc55cSDimitry Andric   }
820349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "Result = " << Result);
821349cc55cSDimitry Andric   llvm_unreachable("Unknown match type detected!");
822fe6060f1SDimitry Andric }
823fe6060f1SDimitry Andric 
82481ad6265SDimitry Andric bool CSKYAsmParser::processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
82581ad6265SDimitry Andric   Inst.setLoc(IDLoc);
82681ad6265SDimitry Andric 
82781ad6265SDimitry Andric   unsigned Opcode;
82881ad6265SDimitry Andric   MCOperand Op;
82981ad6265SDimitry Andric   if (Inst.getOpcode() == CSKY::PseudoLRW16)
83081ad6265SDimitry Andric     Opcode = CSKY::LRW16;
83181ad6265SDimitry Andric   else
83281ad6265SDimitry Andric     Opcode = CSKY::LRW32;
83381ad6265SDimitry Andric 
83481ad6265SDimitry Andric   if (Inst.getOperand(1).isImm()) {
83581ad6265SDimitry Andric     if (isUInt<8>(Inst.getOperand(1).getImm()) &&
83681ad6265SDimitry Andric         Inst.getOperand(0).getReg() <= CSKY::R7) {
83781ad6265SDimitry Andric       Opcode = CSKY::MOVI16;
83881ad6265SDimitry Andric     } else if (getSTI().getFeatureBits()[CSKY::HasE2] &&
83981ad6265SDimitry Andric                isUInt<16>(Inst.getOperand(1).getImm())) {
84081ad6265SDimitry Andric       Opcode = CSKY::MOVI32;
84181ad6265SDimitry Andric     } else {
84281ad6265SDimitry Andric       auto *Expr = getTargetStreamer().addConstantPoolEntry(
84381ad6265SDimitry Andric           MCConstantExpr::create(Inst.getOperand(1).getImm(), getContext()),
84481ad6265SDimitry Andric           Inst.getLoc());
84581ad6265SDimitry Andric       Inst.erase(std::prev(Inst.end()));
84681ad6265SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
84781ad6265SDimitry Andric     }
84881ad6265SDimitry Andric   } else {
84981ad6265SDimitry Andric     const MCExpr *AdjustExpr = nullptr;
85081ad6265SDimitry Andric     if (const CSKYMCExpr *CSKYExpr =
85181ad6265SDimitry Andric             dyn_cast<CSKYMCExpr>(Inst.getOperand(1).getExpr())) {
85281ad6265SDimitry Andric       if (CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSGD ||
85381ad6265SDimitry Andric           CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSIE ||
85481ad6265SDimitry Andric           CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSLDM) {
85581ad6265SDimitry Andric         MCSymbol *Dot = getContext().createNamedTempSymbol();
85681ad6265SDimitry Andric         Out.emitLabel(Dot);
85781ad6265SDimitry Andric         AdjustExpr = MCSymbolRefExpr::create(Dot, getContext());
85881ad6265SDimitry Andric       }
85981ad6265SDimitry Andric     }
86081ad6265SDimitry Andric     auto *Expr = getTargetStreamer().addConstantPoolEntry(
86181ad6265SDimitry Andric         Inst.getOperand(1).getExpr(), Inst.getLoc(), AdjustExpr);
86281ad6265SDimitry Andric     Inst.erase(std::prev(Inst.end()));
86381ad6265SDimitry Andric     Inst.addOperand(MCOperand::createExpr(Expr));
86481ad6265SDimitry Andric   }
86581ad6265SDimitry Andric 
86681ad6265SDimitry Andric   Inst.setOpcode(Opcode);
86781ad6265SDimitry Andric 
86881ad6265SDimitry Andric   Out.emitInstruction(Inst, getSTI());
86981ad6265SDimitry Andric   return false;
87081ad6265SDimitry Andric }
87181ad6265SDimitry Andric 
87281ad6265SDimitry Andric bool CSKYAsmParser::processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
87381ad6265SDimitry Andric   Inst.setLoc(IDLoc);
87481ad6265SDimitry Andric 
87581ad6265SDimitry Andric   if (Inst.getOperand(0).isImm()) {
87681ad6265SDimitry Andric     const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
87781ad6265SDimitry Andric         MCConstantExpr::create(Inst.getOperand(0).getImm(), getContext()),
87881ad6265SDimitry Andric         Inst.getLoc());
87981ad6265SDimitry Andric     Inst.setOpcode(CSKY::JSRI32);
88081ad6265SDimitry Andric     Inst.erase(std::prev(Inst.end()));
88181ad6265SDimitry Andric     Inst.addOperand(MCOperand::createExpr(Expr));
88281ad6265SDimitry Andric   } else {
88381ad6265SDimitry Andric     const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
88481ad6265SDimitry Andric         Inst.getOperand(0).getExpr(), Inst.getLoc());
88581ad6265SDimitry Andric     Inst.setOpcode(CSKY::JBSR32);
88681ad6265SDimitry Andric     Inst.addOperand(MCOperand::createExpr(Expr));
88781ad6265SDimitry Andric   }
88881ad6265SDimitry Andric 
88981ad6265SDimitry Andric   Out.emitInstruction(Inst, getSTI());
89081ad6265SDimitry Andric   return false;
89181ad6265SDimitry Andric }
89281ad6265SDimitry Andric 
89381ad6265SDimitry Andric bool CSKYAsmParser::processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) {
89481ad6265SDimitry Andric   Inst.setLoc(IDLoc);
89581ad6265SDimitry Andric 
89681ad6265SDimitry Andric   if (Inst.getOperand(0).isImm()) {
89781ad6265SDimitry Andric     const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
89881ad6265SDimitry Andric         MCConstantExpr::create(Inst.getOperand(0).getImm(), getContext()),
89981ad6265SDimitry Andric         Inst.getLoc());
90081ad6265SDimitry Andric     Inst.setOpcode(CSKY::JMPI32);
90181ad6265SDimitry Andric     Inst.erase(std::prev(Inst.end()));
90281ad6265SDimitry Andric     Inst.addOperand(MCOperand::createExpr(Expr));
90381ad6265SDimitry Andric   } else {
90481ad6265SDimitry Andric     const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
90581ad6265SDimitry Andric         Inst.getOperand(0).getExpr(), Inst.getLoc());
90681ad6265SDimitry Andric     Inst.setOpcode(CSKY::JBR32);
90781ad6265SDimitry Andric     Inst.addOperand(MCOperand::createExpr(Expr));
90881ad6265SDimitry Andric   }
90981ad6265SDimitry Andric 
91081ad6265SDimitry Andric   Out.emitInstruction(Inst, getSTI());
91181ad6265SDimitry Andric   return false;
91281ad6265SDimitry Andric }
91381ad6265SDimitry Andric 
914349cc55cSDimitry Andric bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
915349cc55cSDimitry Andric                                        OperandVector &Operands,
916349cc55cSDimitry Andric                                        MCStreamer &Out) {
917349cc55cSDimitry Andric 
9180eae32dcSDimitry Andric   switch (Inst.getOpcode()) {
9190eae32dcSDimitry Andric   default:
9200eae32dcSDimitry Andric     break;
9210eae32dcSDimitry Andric   case CSKY::LDQ32:
9220eae32dcSDimitry Andric   case CSKY::STQ32:
923349cc55cSDimitry Andric     if (Inst.getOperand(1).getReg() != CSKY::R4 ||
924349cc55cSDimitry Andric         Inst.getOperand(2).getReg() != CSKY::R7) {
925349cc55cSDimitry Andric       return Error(IDLoc, "Register sequence is not valid. 'r4-r7' expected");
926349cc55cSDimitry Andric     }
927349cc55cSDimitry Andric     Inst.setOpcode(Inst.getOpcode() == CSKY::LDQ32 ? CSKY::LDM32 : CSKY::STM32);
9280eae32dcSDimitry Andric     break;
9290eae32dcSDimitry Andric   case CSKY::SEXT32:
9300eae32dcSDimitry Andric   case CSKY::ZEXT32:
931349cc55cSDimitry Andric     if (Inst.getOperand(2).getImm() < Inst.getOperand(3).getImm())
932349cc55cSDimitry Andric       return Error(IDLoc, "msb must be greater or equal to lsb");
9330eae32dcSDimitry Andric     break;
9340eae32dcSDimitry Andric   case CSKY::INS32:
935349cc55cSDimitry Andric     if (Inst.getOperand(3).getImm() < Inst.getOperand(4).getImm())
936349cc55cSDimitry Andric       return Error(IDLoc, "msb must be greater or equal to lsb");
9370eae32dcSDimitry Andric     break;
9380eae32dcSDimitry Andric   case CSKY::IDLY32:
939349cc55cSDimitry Andric     if (Inst.getOperand(0).getImm() > 32 || Inst.getOperand(0).getImm() < 0)
940349cc55cSDimitry Andric       return Error(IDLoc, "n must be in range [0,32]");
9410eae32dcSDimitry Andric     break;
9420eae32dcSDimitry Andric   case CSKY::ADDC32:
9430eae32dcSDimitry Andric   case CSKY::SUBC32:
9440eae32dcSDimitry Andric   case CSKY::ADDC16:
9450eae32dcSDimitry Andric   case CSKY::SUBC16:
9460eae32dcSDimitry Andric     Inst.erase(std::next(Inst.begin()));
9470eae32dcSDimitry Andric     Inst.erase(std::prev(Inst.end()));
9480eae32dcSDimitry Andric     Inst.insert(std::next(Inst.begin()), MCOperand::createReg(CSKY::C));
9490eae32dcSDimitry Andric     Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
9500eae32dcSDimitry Andric     break;
9510eae32dcSDimitry Andric   case CSKY::CMPNEI32:
9520eae32dcSDimitry Andric   case CSKY::CMPNEI16:
9530eae32dcSDimitry Andric   case CSKY::CMPNE32:
9540eae32dcSDimitry Andric   case CSKY::CMPNE16:
9550eae32dcSDimitry Andric   case CSKY::CMPHSI32:
9560eae32dcSDimitry Andric   case CSKY::CMPHSI16:
9570eae32dcSDimitry Andric   case CSKY::CMPHS32:
9580eae32dcSDimitry Andric   case CSKY::CMPHS16:
9590eae32dcSDimitry Andric   case CSKY::CMPLTI32:
9600eae32dcSDimitry Andric   case CSKY::CMPLTI16:
9610eae32dcSDimitry Andric   case CSKY::CMPLT32:
9620eae32dcSDimitry Andric   case CSKY::CMPLT16:
9630eae32dcSDimitry Andric   case CSKY::BTSTI32:
9640eae32dcSDimitry Andric     Inst.erase(Inst.begin());
9650eae32dcSDimitry Andric     Inst.insert(Inst.begin(), MCOperand::createReg(CSKY::C));
9660eae32dcSDimitry Andric     break;
9670eae32dcSDimitry Andric   case CSKY::MVCV32:
9680eae32dcSDimitry Andric     Inst.erase(std::next(Inst.begin()));
9690eae32dcSDimitry Andric     Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
9700eae32dcSDimitry Andric     break;
97181ad6265SDimitry Andric   case CSKY::PseudoLRW16:
97281ad6265SDimitry Andric   case CSKY::PseudoLRW32:
97381ad6265SDimitry Andric     return processLRW(Inst, IDLoc, Out);
97481ad6265SDimitry Andric   case CSKY::PseudoJSRI32:
97581ad6265SDimitry Andric     return processJSRI(Inst, IDLoc, Out);
97681ad6265SDimitry Andric   case CSKY::PseudoJMPI32:
97781ad6265SDimitry Andric     return processJMPI(Inst, IDLoc, Out);
97881ad6265SDimitry Andric   case CSKY::JBSR32:
97981ad6265SDimitry Andric   case CSKY::JBR16:
98081ad6265SDimitry Andric   case CSKY::JBT16:
98181ad6265SDimitry Andric   case CSKY::JBF16:
98281ad6265SDimitry Andric   case CSKY::JBR32:
98381ad6265SDimitry Andric   case CSKY::JBT32:
98481ad6265SDimitry Andric   case CSKY::JBF32:
98581ad6265SDimitry Andric     unsigned Num = Inst.getNumOperands() - 1;
98681ad6265SDimitry Andric     assert(Inst.getOperand(Num).isExpr());
98781ad6265SDimitry Andric 
98881ad6265SDimitry Andric     const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry(
98981ad6265SDimitry Andric         Inst.getOperand(Num).getExpr(), Inst.getLoc());
99081ad6265SDimitry Andric 
99181ad6265SDimitry Andric     Inst.addOperand(MCOperand::createExpr(Expr));
99281ad6265SDimitry Andric     break;
993349cc55cSDimitry Andric   }
994349cc55cSDimitry Andric 
9950eae32dcSDimitry Andric   emitToStreamer(Out, Inst);
996349cc55cSDimitry Andric   return false;
997fe6060f1SDimitry Andric }
998fe6060f1SDimitry Andric 
999fe6060f1SDimitry Andric // Attempts to match Name as a register (either using the default name or
1000fe6060f1SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon
1001fe6060f1SDimitry Andric // failure, returns true and sets RegNo to 0.
1002349cc55cSDimitry Andric static bool matchRegisterNameHelper(const MCSubtargetInfo &STI,
1003349cc55cSDimitry Andric                                     MCRegister &RegNo, StringRef Name) {
1004fe6060f1SDimitry Andric   RegNo = MatchRegisterName(Name);
1005fe6060f1SDimitry Andric 
1006fe6060f1SDimitry Andric   if (RegNo == CSKY::NoRegister)
1007fe6060f1SDimitry Andric     RegNo = MatchRegisterAltName(Name);
1008fe6060f1SDimitry Andric 
1009fe6060f1SDimitry Andric   return RegNo == CSKY::NoRegister;
1010fe6060f1SDimitry Andric }
1011fe6060f1SDimitry Andric 
1012*bdd1243dSDimitry Andric bool CSKYAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
1013fe6060f1SDimitry Andric                                   SMLoc &EndLoc) {
1014fe6060f1SDimitry Andric   const AsmToken &Tok = getParser().getTok();
1015fe6060f1SDimitry Andric   StartLoc = Tok.getLoc();
1016fe6060f1SDimitry Andric   EndLoc = Tok.getEndLoc();
1017fe6060f1SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
1018fe6060f1SDimitry Andric 
1019349cc55cSDimitry Andric   if (!matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name)) {
1020fe6060f1SDimitry Andric     getParser().Lex(); // Eat identifier token.
1021fe6060f1SDimitry Andric     return false;
1022fe6060f1SDimitry Andric   }
1023fe6060f1SDimitry Andric 
1024349cc55cSDimitry Andric   return MatchOperand_NoMatch;
1025fe6060f1SDimitry Andric }
1026fe6060f1SDimitry Andric 
1027fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegister(OperandVector &Operands) {
1028fe6060f1SDimitry Andric   SMLoc S = getLoc();
1029fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1030fe6060f1SDimitry Andric 
1031fe6060f1SDimitry Andric   switch (getLexer().getKind()) {
1032fe6060f1SDimitry Andric   default:
1033fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1034fe6060f1SDimitry Andric   case AsmToken::Identifier: {
1035fe6060f1SDimitry Andric     StringRef Name = getLexer().getTok().getIdentifier();
1036fe6060f1SDimitry Andric     MCRegister RegNo;
1037fe6060f1SDimitry Andric 
1038349cc55cSDimitry Andric     if (matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name))
1039fe6060f1SDimitry Andric       return MatchOperand_NoMatch;
1040fe6060f1SDimitry Andric 
1041fe6060f1SDimitry Andric     getLexer().Lex();
1042fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createReg(RegNo, S, E));
1043fe6060f1SDimitry Andric 
1044fe6060f1SDimitry Andric     return MatchOperand_Success;
1045fe6060f1SDimitry Andric   }
1046fe6060f1SDimitry Andric   }
1047fe6060f1SDimitry Andric }
1048fe6060f1SDimitry Andric 
1049fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) {
1050fe6060f1SDimitry Andric   assert(getLexer().is(AsmToken::LParen));
1051fe6060f1SDimitry Andric 
1052fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken("(", getLoc()));
1053fe6060f1SDimitry Andric 
1054fe6060f1SDimitry Andric   auto Tok = getParser().Lex(); // Eat '('
1055fe6060f1SDimitry Andric 
1056fe6060f1SDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success) {
1057fe6060f1SDimitry Andric     getLexer().UnLex(Tok);
1058fe6060f1SDimitry Andric     Operands.pop_back();
1059349cc55cSDimitry Andric     return MatchOperand_NoMatch;
1060349cc55cSDimitry Andric   }
1061349cc55cSDimitry Andric 
1062349cc55cSDimitry Andric   if (getLexer().is(AsmToken::RParen)) {
1063349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createToken(")", getLoc()));
1064349cc55cSDimitry Andric     getParser().Lex(); // Eat ')'
1065349cc55cSDimitry Andric     return MatchOperand_Success;
1066fe6060f1SDimitry Andric   }
1067fe6060f1SDimitry Andric 
1068fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::Comma)) {
1069fe6060f1SDimitry Andric     Error(getLoc(), "expected ','");
1070fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
1071fe6060f1SDimitry Andric   }
1072fe6060f1SDimitry Andric 
1073fe6060f1SDimitry Andric   getParser().Lex(); // Eat ','
1074fe6060f1SDimitry Andric 
1075fe6060f1SDimitry Andric   if (parseRegister(Operands) == MatchOperand_Success) {
1076fe6060f1SDimitry Andric     if (getLexer().isNot(AsmToken::LessLess)) {
1077fe6060f1SDimitry Andric       Error(getLoc(), "expected '<<'");
1078fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
1079fe6060f1SDimitry Andric     }
1080fe6060f1SDimitry Andric 
1081fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createToken("<<", getLoc()));
1082fe6060f1SDimitry Andric 
1083fe6060f1SDimitry Andric     getParser().Lex(); // Eat '<<'
1084fe6060f1SDimitry Andric 
1085fe6060f1SDimitry Andric     if (parseImmediate(Operands) != MatchOperand_Success) {
1086fe6060f1SDimitry Andric       Error(getLoc(), "expected imm");
1087fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
1088fe6060f1SDimitry Andric     }
1089fe6060f1SDimitry Andric 
1090fe6060f1SDimitry Andric   } else if (parseImmediate(Operands) != MatchOperand_Success) {
1091fe6060f1SDimitry Andric     Error(getLoc(), "expected imm");
1092fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
1093fe6060f1SDimitry Andric   }
1094fe6060f1SDimitry Andric 
1095fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::RParen)) {
1096fe6060f1SDimitry Andric     Error(getLoc(), "expected ')'");
1097fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
1098fe6060f1SDimitry Andric   }
1099fe6060f1SDimitry Andric 
1100fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken(")", getLoc()));
1101fe6060f1SDimitry Andric 
1102fe6060f1SDimitry Andric   getParser().Lex(); // Eat ')'
1103fe6060f1SDimitry Andric 
1104fe6060f1SDimitry Andric   return MatchOperand_Success;
1105fe6060f1SDimitry Andric }
1106fe6060f1SDimitry Andric 
1107fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
1108fe6060f1SDimitry Andric   switch (getLexer().getKind()) {
1109fe6060f1SDimitry Andric   default:
1110fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1111fe6060f1SDimitry Andric   case AsmToken::LParen:
1112fe6060f1SDimitry Andric   case AsmToken::Minus:
1113fe6060f1SDimitry Andric   case AsmToken::Plus:
1114fe6060f1SDimitry Andric   case AsmToken::Integer:
1115fe6060f1SDimitry Andric   case AsmToken::String:
1116fe6060f1SDimitry Andric     break;
1117fe6060f1SDimitry Andric   }
1118fe6060f1SDimitry Andric 
1119fe6060f1SDimitry Andric   const MCExpr *IdVal;
1120fe6060f1SDimitry Andric   SMLoc S = getLoc();
1121349cc55cSDimitry Andric   if (getParser().parseExpression(IdVal)) {
1122349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1123fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
1124349cc55cSDimitry Andric   }
1125fe6060f1SDimitry Andric 
1126fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1127fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createImm(IdVal, S, E));
1128fe6060f1SDimitry Andric   return MatchOperand_Success;
1129fe6060f1SDimitry Andric }
1130fe6060f1SDimitry Andric 
1131fe6060f1SDimitry Andric /// Looks at a token type and creates the relevant operand from this
1132fe6060f1SDimitry Andric /// information, adding to Operands. If operand was parsed, returns false, else
1133fe6060f1SDimitry Andric /// true.
1134fe6060f1SDimitry Andric bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1135fe6060f1SDimitry Andric   // Check if the current operand has a custom associated parser, if so, try to
1136fe6060f1SDimitry Andric   // custom parse the operand, or fallback to the general approach.
1137fe6060f1SDimitry Andric   OperandMatchResultTy Result =
1138fe6060f1SDimitry Andric       MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1139fe6060f1SDimitry Andric   if (Result == MatchOperand_Success)
1140fe6060f1SDimitry Andric     return false;
1141fe6060f1SDimitry Andric   if (Result == MatchOperand_ParseFail)
1142fe6060f1SDimitry Andric     return true;
1143fe6060f1SDimitry Andric 
1144fe6060f1SDimitry Andric   // Attempt to parse token as register
1145349cc55cSDimitry Andric   auto Res = parseRegister(Operands);
1146349cc55cSDimitry Andric   if (Res == MatchOperand_Success)
1147fe6060f1SDimitry Andric     return false;
1148349cc55cSDimitry Andric   else if (Res == MatchOperand_ParseFail)
1149349cc55cSDimitry Andric     return true;
1150fe6060f1SDimitry Andric 
1151fe6060f1SDimitry Andric   // Attempt to parse token as (register, imm)
1152349cc55cSDimitry Andric   if (getLexer().is(AsmToken::LParen)) {
1153349cc55cSDimitry Andric     Res = parseBaseRegImm(Operands);
1154349cc55cSDimitry Andric     if (Res == MatchOperand_Success)
1155fe6060f1SDimitry Andric       return false;
1156349cc55cSDimitry Andric     else if (Res == MatchOperand_ParseFail)
1157349cc55cSDimitry Andric       return true;
1158349cc55cSDimitry Andric   }
1159fe6060f1SDimitry Andric 
1160349cc55cSDimitry Andric   Res = parseImmediate(Operands);
1161349cc55cSDimitry Andric   if (Res == MatchOperand_Success)
1162fe6060f1SDimitry Andric     return false;
1163349cc55cSDimitry Andric   else if (Res == MatchOperand_ParseFail)
1164349cc55cSDimitry Andric     return true;
1165fe6060f1SDimitry Andric 
1166fe6060f1SDimitry Andric   // Finally we have exhausted all options and must declare defeat.
1167fe6060f1SDimitry Andric   Error(getLoc(), "unknown operand");
1168fe6060f1SDimitry Andric   return true;
1169fe6060f1SDimitry Andric }
1170fe6060f1SDimitry Andric 
1171fe6060f1SDimitry Andric OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
1172fe6060f1SDimitry Andric   SMLoc S = getLoc();
1173fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1174349cc55cSDimitry Andric   const MCExpr *Res;
1175fe6060f1SDimitry Andric 
1176fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier)
1177fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1178fe6060f1SDimitry Andric 
1179fe6060f1SDimitry Andric   StringRef Identifier;
1180349cc55cSDimitry Andric   AsmToken Tok = getLexer().getTok();
1181349cc55cSDimitry Andric 
1182349cc55cSDimitry Andric   if (getParser().parseIdentifier(Identifier)) {
1183349cc55cSDimitry Andric     Error(getLoc(), "unknown identifier");
1184fe6060f1SDimitry Andric     return MatchOperand_ParseFail;
1185349cc55cSDimitry Andric   }
1186fe6060f1SDimitry Andric 
1187fe6060f1SDimitry Andric   CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
1188fe6060f1SDimitry Andric   if (Identifier.consume_back("@GOT"))
1189fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOT;
1190fe6060f1SDimitry Andric   else if (Identifier.consume_back("@GOTOFF"))
1191fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOTOFF;
1192fe6060f1SDimitry Andric   else if (Identifier.consume_back("@PLT"))
1193fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_PLT;
1194fe6060f1SDimitry Andric   else if (Identifier.consume_back("@GOTPC"))
1195fe6060f1SDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOTPC;
1196349cc55cSDimitry Andric   else if (Identifier.consume_back("@TLSGD32"))
1197349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSGD;
1198349cc55cSDimitry Andric   else if (Identifier.consume_back("@GOTTPOFF"))
1199349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSIE;
1200349cc55cSDimitry Andric   else if (Identifier.consume_back("@TPOFF"))
1201349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSLE;
1202349cc55cSDimitry Andric   else if (Identifier.consume_back("@TLSLDM32"))
1203349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSLDM;
1204349cc55cSDimitry Andric   else if (Identifier.consume_back("@TLSLDO32"))
1205349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_TLSLDO;
1206fe6060f1SDimitry Andric 
1207349cc55cSDimitry Andric   MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1208fe6060f1SDimitry Andric 
1209349cc55cSDimitry Andric   if (!Sym)
1210349cc55cSDimitry Andric     Sym = getContext().getOrCreateSymbol(Identifier);
1211349cc55cSDimitry Andric 
1212349cc55cSDimitry Andric   if (Sym->isVariable()) {
1213349cc55cSDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1214349cc55cSDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
1215349cc55cSDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1216349cc55cSDimitry Andric       Error(getLoc(), "unknown symbol");
1217349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1218349cc55cSDimitry Andric     }
1219349cc55cSDimitry Andric     Res = V;
1220349cc55cSDimitry Andric   } else
1221349cc55cSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1222349cc55cSDimitry Andric 
1223349cc55cSDimitry Andric   MCBinaryExpr::Opcode Opcode;
1224349cc55cSDimitry Andric   switch (getLexer().getKind()) {
1225349cc55cSDimitry Andric   default:
1226fe6060f1SDimitry Andric     if (Kind != CSKYMCExpr::VK_CSKY_None)
1227fe6060f1SDimitry Andric       Res = CSKYMCExpr::create(Res, Kind, getContext());
1228fe6060f1SDimitry Andric 
1229fe6060f1SDimitry Andric     Operands.push_back(CSKYOperand::createImm(Res, S, E));
1230fe6060f1SDimitry Andric     return MatchOperand_Success;
1231349cc55cSDimitry Andric   case AsmToken::Plus:
1232349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Add;
1233349cc55cSDimitry Andric     break;
1234349cc55cSDimitry Andric   case AsmToken::Minus:
1235349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Sub;
1236349cc55cSDimitry Andric     break;
1237349cc55cSDimitry Andric   }
1238349cc55cSDimitry Andric 
1239349cc55cSDimitry Andric   getLexer().Lex(); // eat + or -
1240349cc55cSDimitry Andric 
1241349cc55cSDimitry Andric   const MCExpr *Expr;
1242349cc55cSDimitry Andric   if (getParser().parseExpression(Expr)) {
1243349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1244349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1245349cc55cSDimitry Andric   }
1246349cc55cSDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1247349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createImm(Res, S, E));
1248349cc55cSDimitry Andric   return MatchOperand_Success;
1249349cc55cSDimitry Andric }
1250349cc55cSDimitry Andric 
1251349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parseDataSymbol(OperandVector &Operands) {
1252349cc55cSDimitry Andric   SMLoc S = getLoc();
1253349cc55cSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1254349cc55cSDimitry Andric   const MCExpr *Res;
1255349cc55cSDimitry Andric 
1256349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::LBrac)
1257349cc55cSDimitry Andric     return MatchOperand_NoMatch;
1258349cc55cSDimitry Andric 
1259349cc55cSDimitry Andric   getLexer().Lex(); // Eat '['.
1260349cc55cSDimitry Andric 
1261349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier) {
1262349cc55cSDimitry Andric     const MCExpr *Expr;
1263349cc55cSDimitry Andric     if (getParser().parseExpression(Expr)) {
1264349cc55cSDimitry Andric       Error(getLoc(), "unknown expression");
1265349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1266349cc55cSDimitry Andric     }
1267349cc55cSDimitry Andric 
1268349cc55cSDimitry Andric     if (getLexer().getKind() != AsmToken::RBrac) {
1269349cc55cSDimitry Andric       Error(getLoc(), "expected ]");
1270349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1271349cc55cSDimitry Andric     }
1272349cc55cSDimitry Andric 
1273349cc55cSDimitry Andric     getLexer().Lex(); // Eat ']'.
1274349cc55cSDimitry Andric 
1275349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1276349cc55cSDimitry Andric     return MatchOperand_Success;
1277349cc55cSDimitry Andric   }
1278349cc55cSDimitry Andric 
1279349cc55cSDimitry Andric   AsmToken Tok = getLexer().getTok();
1280349cc55cSDimitry Andric   StringRef Identifier;
1281349cc55cSDimitry Andric 
1282349cc55cSDimitry Andric   if (getParser().parseIdentifier(Identifier)) {
1283349cc55cSDimitry Andric     Error(getLoc(), "unknown identifier " + Identifier);
1284349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1285349cc55cSDimitry Andric   }
1286349cc55cSDimitry Andric 
1287349cc55cSDimitry Andric   CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
1288349cc55cSDimitry Andric   if (Identifier.consume_back("@GOT"))
1289349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4;
1290349cc55cSDimitry Andric   else if (Identifier.consume_back("@PLT"))
1291349cc55cSDimitry Andric     Kind = CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4;
1292349cc55cSDimitry Andric 
1293349cc55cSDimitry Andric   MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1294349cc55cSDimitry Andric 
1295349cc55cSDimitry Andric   if (!Sym)
1296349cc55cSDimitry Andric     Sym = getContext().getOrCreateSymbol(Identifier);
1297349cc55cSDimitry Andric 
1298349cc55cSDimitry Andric   if (Sym->isVariable()) {
1299349cc55cSDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1300349cc55cSDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
1301349cc55cSDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1302349cc55cSDimitry Andric       Error(getLoc(), "unknown symbol");
1303349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1304349cc55cSDimitry Andric     }
1305349cc55cSDimitry Andric     Res = V;
1306349cc55cSDimitry Andric   } else {
1307349cc55cSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1308349cc55cSDimitry Andric   }
1309349cc55cSDimitry Andric 
1310349cc55cSDimitry Andric   MCBinaryExpr::Opcode Opcode;
1311349cc55cSDimitry Andric   switch (getLexer().getKind()) {
1312349cc55cSDimitry Andric   default:
1313349cc55cSDimitry Andric     Error(getLoc(), "unknown symbol");
1314349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1315349cc55cSDimitry Andric   case AsmToken::RBrac:
1316349cc55cSDimitry Andric 
1317349cc55cSDimitry Andric     getLexer().Lex(); // Eat ']'.
1318349cc55cSDimitry Andric 
1319349cc55cSDimitry Andric     if (Kind != CSKYMCExpr::VK_CSKY_None)
1320349cc55cSDimitry Andric       Res = CSKYMCExpr::create(Res, Kind, getContext());
1321349cc55cSDimitry Andric 
1322349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1323349cc55cSDimitry Andric     return MatchOperand_Success;
1324349cc55cSDimitry Andric   case AsmToken::Plus:
1325349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Add;
1326349cc55cSDimitry Andric     break;
1327349cc55cSDimitry Andric   case AsmToken::Minus:
1328349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Sub;
1329349cc55cSDimitry Andric     break;
1330349cc55cSDimitry Andric   }
1331349cc55cSDimitry Andric 
1332349cc55cSDimitry Andric   getLexer().Lex(); // eat + or -
1333349cc55cSDimitry Andric 
1334349cc55cSDimitry Andric   const MCExpr *Expr;
1335349cc55cSDimitry Andric   if (getParser().parseExpression(Expr)) {
1336349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1337349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1338349cc55cSDimitry Andric   }
1339349cc55cSDimitry Andric 
1340349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::RBrac) {
1341349cc55cSDimitry Andric     Error(getLoc(), "expected ']'");
1342349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1343349cc55cSDimitry Andric   }
1344349cc55cSDimitry Andric 
1345349cc55cSDimitry Andric   getLexer().Lex(); // Eat ']'.
1346349cc55cSDimitry Andric 
1347349cc55cSDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1348349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1349349cc55cSDimitry Andric   return MatchOperand_Success;
1350fe6060f1SDimitry Andric }
1351fe6060f1SDimitry Andric 
1352fe6060f1SDimitry Andric OperandMatchResultTy
1353fe6060f1SDimitry Andric CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
1354fe6060f1SDimitry Andric   SMLoc S = getLoc();
1355fe6060f1SDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1356349cc55cSDimitry Andric   const MCExpr *Res;
1357fe6060f1SDimitry Andric 
1358fe6060f1SDimitry Andric   if (getLexer().getKind() != AsmToken::LBrac)
1359fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1360fe6060f1SDimitry Andric 
1361fe6060f1SDimitry Andric   getLexer().Lex(); // Eat '['.
1362fe6060f1SDimitry Andric 
1363349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::Identifier) {
1364349cc55cSDimitry Andric     const MCExpr *Expr;
1365349cc55cSDimitry Andric     if (getParser().parseExpression(Expr)) {
1366349cc55cSDimitry Andric       Error(getLoc(), "unknown expression");
1367fe6060f1SDimitry Andric       return MatchOperand_ParseFail;
1368349cc55cSDimitry Andric     }
1369fe6060f1SDimitry Andric 
1370349cc55cSDimitry Andric     if (getLexer().getKind() != AsmToken::RBrac) {
1371349cc55cSDimitry Andric       Error(getLoc(), "expected ']'");
1372349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1373349cc55cSDimitry Andric     }
1374fe6060f1SDimitry Andric 
1375fe6060f1SDimitry Andric     getLexer().Lex(); // Eat ']'.
1376fe6060f1SDimitry Andric 
1377349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E));
1378349cc55cSDimitry Andric     return MatchOperand_Success;
1379349cc55cSDimitry Andric   }
1380349cc55cSDimitry Andric 
1381349cc55cSDimitry Andric   AsmToken Tok = getLexer().getTok();
1382349cc55cSDimitry Andric   StringRef Identifier;
1383349cc55cSDimitry Andric 
1384349cc55cSDimitry Andric   if (getParser().parseIdentifier(Identifier)) {
1385349cc55cSDimitry Andric     Error(getLoc(), "unknown identifier");
1386349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1387349cc55cSDimitry Andric   }
1388349cc55cSDimitry Andric 
1389349cc55cSDimitry Andric   MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier);
1390349cc55cSDimitry Andric 
1391349cc55cSDimitry Andric   if (!Sym)
1392349cc55cSDimitry Andric     Sym = getContext().getOrCreateSymbol(Identifier);
1393349cc55cSDimitry Andric 
1394349cc55cSDimitry Andric   if (Sym->isVariable()) {
1395349cc55cSDimitry Andric     const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1396349cc55cSDimitry Andric     if (!isa<MCSymbolRefExpr>(V)) {
1397349cc55cSDimitry Andric       getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1398349cc55cSDimitry Andric       Error(getLoc(), "unknown symbol");
1399349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1400349cc55cSDimitry Andric     }
1401349cc55cSDimitry Andric     Res = V;
1402349cc55cSDimitry Andric   } else {
1403349cc55cSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1404349cc55cSDimitry Andric   }
1405349cc55cSDimitry Andric 
1406349cc55cSDimitry Andric   MCBinaryExpr::Opcode Opcode;
1407349cc55cSDimitry Andric   switch (getLexer().getKind()) {
1408349cc55cSDimitry Andric   default:
1409349cc55cSDimitry Andric     Error(getLoc(), "unknown symbol");
1410349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1411349cc55cSDimitry Andric   case AsmToken::RBrac:
1412349cc55cSDimitry Andric 
1413349cc55cSDimitry Andric     getLexer().Lex(); // Eat ']'.
1414349cc55cSDimitry Andric 
1415349cc55cSDimitry Andric     Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1416349cc55cSDimitry Andric     return MatchOperand_Success;
1417349cc55cSDimitry Andric   case AsmToken::Plus:
1418349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Add;
1419349cc55cSDimitry Andric     break;
1420349cc55cSDimitry Andric   case AsmToken::Minus:
1421349cc55cSDimitry Andric     Opcode = MCBinaryExpr::Sub;
1422349cc55cSDimitry Andric     break;
1423349cc55cSDimitry Andric   }
1424349cc55cSDimitry Andric 
1425349cc55cSDimitry Andric   getLexer().Lex(); // eat + or -
1426349cc55cSDimitry Andric 
1427349cc55cSDimitry Andric   const MCExpr *Expr;
1428349cc55cSDimitry Andric   if (getParser().parseExpression(Expr)) {
1429349cc55cSDimitry Andric     Error(getLoc(), "unknown expression");
1430349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1431349cc55cSDimitry Andric   }
1432349cc55cSDimitry Andric 
1433349cc55cSDimitry Andric   if (getLexer().getKind() != AsmToken::RBrac) {
1434349cc55cSDimitry Andric     Error(getLoc(), "expected ']'");
1435349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1436349cc55cSDimitry Andric   }
1437349cc55cSDimitry Andric 
1438349cc55cSDimitry Andric   getLexer().Lex(); // Eat ']'.
1439349cc55cSDimitry Andric 
1440349cc55cSDimitry Andric   Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1441349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E));
1442349cc55cSDimitry Andric   return MatchOperand_Success;
1443349cc55cSDimitry Andric }
1444349cc55cSDimitry Andric 
1445349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parsePSRFlag(OperandVector &Operands) {
1446349cc55cSDimitry Andric   SMLoc S = getLoc();
1447349cc55cSDimitry Andric   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1448349cc55cSDimitry Andric 
1449349cc55cSDimitry Andric   unsigned Flag = 0;
1450349cc55cSDimitry Andric 
1451349cc55cSDimitry Andric   while (getLexer().isNot(AsmToken::EndOfStatement)) {
1452349cc55cSDimitry Andric     StringRef Identifier;
1453349cc55cSDimitry Andric     if (getParser().parseIdentifier(Identifier)) {
1454349cc55cSDimitry Andric       Error(getLoc(), "unknown identifier " + Identifier);
1455349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1456349cc55cSDimitry Andric     }
1457349cc55cSDimitry Andric 
1458349cc55cSDimitry Andric     if (Identifier == "sie")
1459349cc55cSDimitry Andric       Flag = (1 << 4) | Flag;
1460349cc55cSDimitry Andric     else if (Identifier == "ee")
1461349cc55cSDimitry Andric       Flag = (1 << 3) | Flag;
1462349cc55cSDimitry Andric     else if (Identifier == "ie")
1463349cc55cSDimitry Andric       Flag = (1 << 2) | Flag;
1464349cc55cSDimitry Andric     else if (Identifier == "fe")
1465349cc55cSDimitry Andric       Flag = (1 << 1) | Flag;
1466349cc55cSDimitry Andric     else if (Identifier == "af")
1467349cc55cSDimitry Andric       Flag = (1 << 0) | Flag;
1468349cc55cSDimitry Andric     else {
1469349cc55cSDimitry Andric       Error(getLoc(), "expected " + Identifier);
1470349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1471349cc55cSDimitry Andric     }
1472349cc55cSDimitry Andric 
1473349cc55cSDimitry Andric     if (getLexer().is(AsmToken::EndOfStatement))
1474349cc55cSDimitry Andric       break;
1475349cc55cSDimitry Andric 
1476349cc55cSDimitry Andric     if (getLexer().is(AsmToken::Comma)) {
1477349cc55cSDimitry Andric       getLexer().Lex(); // eat ','
1478349cc55cSDimitry Andric     } else {
1479349cc55cSDimitry Andric       Error(getLoc(), "expected ,");
1480349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1481349cc55cSDimitry Andric     }
1482349cc55cSDimitry Andric   }
1483349cc55cSDimitry Andric 
1484349cc55cSDimitry Andric   Operands.push_back(
1485349cc55cSDimitry Andric       CSKYOperand::createImm(MCConstantExpr::create(Flag, getContext()), S, E));
1486349cc55cSDimitry Andric   return MatchOperand_Success;
1487349cc55cSDimitry Andric }
1488349cc55cSDimitry Andric 
1489349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegSeq(OperandVector &Operands) {
1490349cc55cSDimitry Andric   SMLoc S = getLoc();
1491349cc55cSDimitry Andric 
1492349cc55cSDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success)
1493349cc55cSDimitry Andric     return MatchOperand_NoMatch;
1494349cc55cSDimitry Andric 
1495349cc55cSDimitry Andric   auto Ry = Operands.back()->getReg();
1496349cc55cSDimitry Andric   Operands.pop_back();
1497349cc55cSDimitry Andric 
1498349cc55cSDimitry Andric   if (getLexer().isNot(AsmToken::Minus)) {
1499349cc55cSDimitry Andric     Error(getLoc(), "expected '-'");
1500349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1501349cc55cSDimitry Andric   }
1502349cc55cSDimitry Andric 
1503349cc55cSDimitry Andric   getLexer().Lex(); // eat '-'
1504349cc55cSDimitry Andric 
1505349cc55cSDimitry Andric   if (parseRegister(Operands) != MatchOperand_Success) {
1506349cc55cSDimitry Andric     Error(getLoc(), "invalid register");
1507349cc55cSDimitry Andric     return MatchOperand_ParseFail;
1508349cc55cSDimitry Andric   }
1509349cc55cSDimitry Andric 
1510349cc55cSDimitry Andric   auto Rz = Operands.back()->getReg();
1511349cc55cSDimitry Andric   Operands.pop_back();
1512349cc55cSDimitry Andric 
1513349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createRegSeq(Ry, Rz, S));
1514349cc55cSDimitry Andric   return MatchOperand_Success;
1515349cc55cSDimitry Andric }
1516349cc55cSDimitry Andric 
1517349cc55cSDimitry Andric OperandMatchResultTy CSKYAsmParser::parseRegList(OperandVector &Operands) {
1518349cc55cSDimitry Andric   SMLoc S = getLoc();
1519349cc55cSDimitry Andric 
1520349cc55cSDimitry Andric   SmallVector<unsigned, 4> reglist;
1521349cc55cSDimitry Andric 
1522349cc55cSDimitry Andric   while (true) {
1523349cc55cSDimitry Andric 
1524349cc55cSDimitry Andric     if (parseRegister(Operands) != MatchOperand_Success) {
1525349cc55cSDimitry Andric       Error(getLoc(), "invalid register");
1526349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1527349cc55cSDimitry Andric     }
1528349cc55cSDimitry Andric 
1529349cc55cSDimitry Andric     auto Ry = Operands.back()->getReg();
1530349cc55cSDimitry Andric     Operands.pop_back();
1531349cc55cSDimitry Andric 
1532349cc55cSDimitry Andric     if (getLexer().is(AsmToken::Minus)) {
1533349cc55cSDimitry Andric       getLexer().Lex(); // eat '-'
1534349cc55cSDimitry Andric 
1535349cc55cSDimitry Andric       if (parseRegister(Operands) != MatchOperand_Success) {
1536349cc55cSDimitry Andric         Error(getLoc(), "invalid register");
1537349cc55cSDimitry Andric         return MatchOperand_ParseFail;
1538349cc55cSDimitry Andric       }
1539349cc55cSDimitry Andric 
1540349cc55cSDimitry Andric       auto Rz = Operands.back()->getReg();
1541349cc55cSDimitry Andric       Operands.pop_back();
1542349cc55cSDimitry Andric 
1543349cc55cSDimitry Andric       reglist.push_back(Ry);
1544349cc55cSDimitry Andric       reglist.push_back(Rz);
1545349cc55cSDimitry Andric 
1546349cc55cSDimitry Andric       if (getLexer().is(AsmToken::Comma))
1547349cc55cSDimitry Andric         getLexer().Lex(); // eat ','
1548349cc55cSDimitry Andric       else if (getLexer().is(AsmToken::EndOfStatement))
1549349cc55cSDimitry Andric         break;
1550349cc55cSDimitry Andric 
1551349cc55cSDimitry Andric     } else if (getLexer().is(AsmToken::Comma)) {
1552349cc55cSDimitry Andric       reglist.push_back(Ry);
1553349cc55cSDimitry Andric       reglist.push_back(Ry);
1554349cc55cSDimitry Andric 
1555349cc55cSDimitry Andric       getLexer().Lex(); // eat ','
1556349cc55cSDimitry Andric     } else if (getLexer().is(AsmToken::EndOfStatement)) {
1557349cc55cSDimitry Andric       reglist.push_back(Ry);
1558349cc55cSDimitry Andric       reglist.push_back(Ry);
1559349cc55cSDimitry Andric       break;
1560349cc55cSDimitry Andric     } else {
1561349cc55cSDimitry Andric       Error(getLoc(), "invalid register list");
1562349cc55cSDimitry Andric       return MatchOperand_ParseFail;
1563349cc55cSDimitry Andric     }
1564349cc55cSDimitry Andric   }
1565349cc55cSDimitry Andric 
1566349cc55cSDimitry Andric   Operands.push_back(CSKYOperand::createRegList(reglist, S));
1567fe6060f1SDimitry Andric   return MatchOperand_Success;
1568fe6060f1SDimitry Andric }
1569fe6060f1SDimitry Andric 
1570fe6060f1SDimitry Andric bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1571fe6060f1SDimitry Andric                                      SMLoc NameLoc, OperandVector &Operands) {
1572fe6060f1SDimitry Andric   // First operand is token for instruction.
1573fe6060f1SDimitry Andric   Operands.push_back(CSKYOperand::createToken(Name, NameLoc));
1574fe6060f1SDimitry Andric 
1575fe6060f1SDimitry Andric   // If there are no more operands, then finish.
1576fe6060f1SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement))
1577fe6060f1SDimitry Andric     return false;
1578fe6060f1SDimitry Andric 
1579fe6060f1SDimitry Andric   // Parse first operand.
1580fe6060f1SDimitry Andric   if (parseOperand(Operands, Name))
1581fe6060f1SDimitry Andric     return true;
1582fe6060f1SDimitry Andric 
1583fe6060f1SDimitry Andric   // Parse until end of statement, consuming commas between operands.
1584fe6060f1SDimitry Andric   while (getLexer().is(AsmToken::Comma)) {
1585fe6060f1SDimitry Andric     // Consume comma token.
1586fe6060f1SDimitry Andric     getLexer().Lex();
1587fe6060f1SDimitry Andric 
1588fe6060f1SDimitry Andric     // Parse next operand.
1589fe6060f1SDimitry Andric     if (parseOperand(Operands, Name))
1590fe6060f1SDimitry Andric       return true;
1591fe6060f1SDimitry Andric   }
1592fe6060f1SDimitry Andric 
1593fe6060f1SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1594fe6060f1SDimitry Andric     SMLoc Loc = getLexer().getLoc();
1595fe6060f1SDimitry Andric     getParser().eatToEndOfStatement();
1596fe6060f1SDimitry Andric     return Error(Loc, "unexpected token");
1597fe6060f1SDimitry Andric   }
1598fe6060f1SDimitry Andric 
1599fe6060f1SDimitry Andric   getParser().Lex(); // Consume the EndOfStatement.
1600fe6060f1SDimitry Andric   return false;
1601fe6060f1SDimitry Andric }
1602fe6060f1SDimitry Andric 
1603*bdd1243dSDimitry Andric OperandMatchResultTy CSKYAsmParser::tryParseRegister(MCRegister &RegNo,
1604fe6060f1SDimitry Andric                                                      SMLoc &StartLoc,
1605fe6060f1SDimitry Andric                                                      SMLoc &EndLoc) {
1606fe6060f1SDimitry Andric   const AsmToken &Tok = getParser().getTok();
1607fe6060f1SDimitry Andric   StartLoc = Tok.getLoc();
1608fe6060f1SDimitry Andric   EndLoc = Tok.getEndLoc();
1609fe6060f1SDimitry Andric 
1610fe6060f1SDimitry Andric   StringRef Name = getLexer().getTok().getIdentifier();
1611fe6060f1SDimitry Andric 
1612349cc55cSDimitry Andric   if (matchRegisterNameHelper(getSTI(), (MCRegister &)RegNo, Name))
1613fe6060f1SDimitry Andric     return MatchOperand_NoMatch;
1614fe6060f1SDimitry Andric 
1615fe6060f1SDimitry Andric   getParser().Lex(); // Eat identifier token.
1616fe6060f1SDimitry Andric   return MatchOperand_Success;
1617fe6060f1SDimitry Andric }
1618fe6060f1SDimitry Andric 
161981ad6265SDimitry Andric bool CSKYAsmParser::ParseDirective(AsmToken DirectiveID) {
162081ad6265SDimitry Andric   // This returns false if this function recognizes the directive
162181ad6265SDimitry Andric   // regardless of whether it is successfully handles or reports an
162281ad6265SDimitry Andric   // error. Otherwise it returns true to give the generic parser a
162381ad6265SDimitry Andric   // chance at recognizing it.
162481ad6265SDimitry Andric   StringRef IDVal = DirectiveID.getString();
162581ad6265SDimitry Andric 
162681ad6265SDimitry Andric   if (IDVal == ".csky_attribute")
162781ad6265SDimitry Andric     return parseDirectiveAttribute();
162881ad6265SDimitry Andric 
162981ad6265SDimitry Andric   return true;
163081ad6265SDimitry Andric }
163181ad6265SDimitry Andric 
163281ad6265SDimitry Andric /// parseDirectiveAttribute
163381ad6265SDimitry Andric ///  ::= .attribute expression ',' ( expression | "string" )
163481ad6265SDimitry Andric bool CSKYAsmParser::parseDirectiveAttribute() {
163581ad6265SDimitry Andric   MCAsmParser &Parser = getParser();
163681ad6265SDimitry Andric   int64_t Tag;
163781ad6265SDimitry Andric   SMLoc TagLoc;
163881ad6265SDimitry Andric   TagLoc = Parser.getTok().getLoc();
163981ad6265SDimitry Andric   if (Parser.getTok().is(AsmToken::Identifier)) {
164081ad6265SDimitry Andric     StringRef Name = Parser.getTok().getIdentifier();
1641*bdd1243dSDimitry Andric     std::optional<unsigned> Ret =
164281ad6265SDimitry Andric         ELFAttrs::attrTypeFromString(Name, CSKYAttrs::getCSKYAttributeTags());
1643*bdd1243dSDimitry Andric     if (!Ret) {
164481ad6265SDimitry Andric       Error(TagLoc, "attribute name not recognised: " + Name);
164581ad6265SDimitry Andric       return false;
164681ad6265SDimitry Andric     }
1647*bdd1243dSDimitry Andric     Tag = *Ret;
164881ad6265SDimitry Andric     Parser.Lex();
164981ad6265SDimitry Andric   } else {
165081ad6265SDimitry Andric     const MCExpr *AttrExpr;
165181ad6265SDimitry Andric 
165281ad6265SDimitry Andric     TagLoc = Parser.getTok().getLoc();
165381ad6265SDimitry Andric     if (Parser.parseExpression(AttrExpr))
165481ad6265SDimitry Andric       return true;
165581ad6265SDimitry Andric 
165681ad6265SDimitry Andric     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
165781ad6265SDimitry Andric     if (check(!CE, TagLoc, "expected numeric constant"))
165881ad6265SDimitry Andric       return true;
165981ad6265SDimitry Andric 
166081ad6265SDimitry Andric     Tag = CE->getValue();
166181ad6265SDimitry Andric   }
166281ad6265SDimitry Andric 
166381ad6265SDimitry Andric   if (Parser.parseToken(AsmToken::Comma, "comma expected"))
166481ad6265SDimitry Andric     return true;
166581ad6265SDimitry Andric 
166681ad6265SDimitry Andric   StringRef StringValue;
166781ad6265SDimitry Andric   int64_t IntegerValue = 0;
166881ad6265SDimitry Andric   bool IsIntegerValue = ((Tag != CSKYAttrs::CSKY_ARCH_NAME) &&
166981ad6265SDimitry Andric                          (Tag != CSKYAttrs::CSKY_CPU_NAME) &&
167081ad6265SDimitry Andric                          (Tag != CSKYAttrs::CSKY_FPU_NUMBER_MODULE));
167181ad6265SDimitry Andric 
167281ad6265SDimitry Andric   SMLoc ValueExprLoc = Parser.getTok().getLoc();
167381ad6265SDimitry Andric   if (IsIntegerValue) {
167481ad6265SDimitry Andric     const MCExpr *ValueExpr;
167581ad6265SDimitry Andric     if (Parser.parseExpression(ValueExpr))
167681ad6265SDimitry Andric       return true;
167781ad6265SDimitry Andric 
167881ad6265SDimitry Andric     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
167981ad6265SDimitry Andric     if (!CE)
168081ad6265SDimitry Andric       return Error(ValueExprLoc, "expected numeric constant");
168181ad6265SDimitry Andric     IntegerValue = CE->getValue();
168281ad6265SDimitry Andric   } else {
168381ad6265SDimitry Andric     if (Parser.getTok().isNot(AsmToken::String))
168481ad6265SDimitry Andric       return Error(Parser.getTok().getLoc(), "expected string constant");
168581ad6265SDimitry Andric 
168681ad6265SDimitry Andric     StringValue = Parser.getTok().getStringContents();
168781ad6265SDimitry Andric     Parser.Lex();
168881ad6265SDimitry Andric   }
168981ad6265SDimitry Andric 
169081ad6265SDimitry Andric   if (Parser.parseEOL())
169181ad6265SDimitry Andric     return true;
169281ad6265SDimitry Andric 
169381ad6265SDimitry Andric   if (IsIntegerValue)
169481ad6265SDimitry Andric     getTargetStreamer().emitAttribute(Tag, IntegerValue);
169581ad6265SDimitry Andric   else if (Tag != CSKYAttrs::CSKY_ARCH_NAME && Tag != CSKYAttrs::CSKY_CPU_NAME)
169681ad6265SDimitry Andric     getTargetStreamer().emitTextAttribute(Tag, StringValue);
169781ad6265SDimitry Andric   else {
169881ad6265SDimitry Andric     CSKY::ArchKind ID = (Tag == CSKYAttrs::CSKY_ARCH_NAME)
169981ad6265SDimitry Andric                             ? CSKY::parseArch(StringValue)
170081ad6265SDimitry Andric                             : CSKY::parseCPUArch(StringValue);
170181ad6265SDimitry Andric     if (ID == CSKY::ArchKind::INVALID)
170281ad6265SDimitry Andric       return Error(ValueExprLoc, (Tag == CSKYAttrs::CSKY_ARCH_NAME)
170381ad6265SDimitry Andric                                      ? "unknown arch name"
170481ad6265SDimitry Andric                                      : "unknown cpu name");
170581ad6265SDimitry Andric 
170681ad6265SDimitry Andric     getTargetStreamer().emitTextAttribute(Tag, StringValue);
170781ad6265SDimitry Andric   }
170881ad6265SDimitry Andric 
170981ad6265SDimitry Andric   return false;
171081ad6265SDimitry Andric }
171181ad6265SDimitry Andric 
171281ad6265SDimitry Andric unsigned CSKYAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
171381ad6265SDimitry Andric                                                    unsigned Kind) {
171481ad6265SDimitry Andric   CSKYOperand &Op = static_cast<CSKYOperand &>(AsmOp);
171581ad6265SDimitry Andric 
171681ad6265SDimitry Andric   if (!Op.isReg())
171781ad6265SDimitry Andric     return Match_InvalidOperand;
171881ad6265SDimitry Andric 
171981ad6265SDimitry Andric   MCRegister Reg = Op.getReg();
172081ad6265SDimitry Andric 
172181ad6265SDimitry Andric   if (CSKYMCRegisterClasses[CSKY::FPR32RegClassID].contains(Reg)) {
172281ad6265SDimitry Andric     // As the parser couldn't differentiate an FPR64 from an FPR32, coerce the
172381ad6265SDimitry Andric     // register from FPR32 to FPR64 if necessary.
172481ad6265SDimitry Andric     if (Kind == MCK_FPR64 || Kind == MCK_sFPR64) {
172581ad6265SDimitry Andric       Op.Reg.RegNum = convertFPR32ToFPR64(Reg);
172681ad6265SDimitry Andric       if (Kind == MCK_sFPR64 &&
172781ad6265SDimitry Andric           (Op.Reg.RegNum < CSKY::F0_64 || Op.Reg.RegNum > CSKY::F15_64))
172881ad6265SDimitry Andric         return Match_InvalidRegOutOfRange;
172981ad6265SDimitry Andric       if (Kind == MCK_FPR64 &&
173081ad6265SDimitry Andric           (Op.Reg.RegNum < CSKY::F0_64 || Op.Reg.RegNum > CSKY::F31_64))
173181ad6265SDimitry Andric         return Match_InvalidRegOutOfRange;
173281ad6265SDimitry Andric       return Match_Success;
173381ad6265SDimitry Andric     }
173481ad6265SDimitry Andric   }
173581ad6265SDimitry Andric 
173681ad6265SDimitry Andric   if (CSKYMCRegisterClasses[CSKY::GPRRegClassID].contains(Reg)) {
173781ad6265SDimitry Andric     if (Kind == MCK_GPRPair) {
173881ad6265SDimitry Andric       Op.Reg.RegNum = MRI->getEncodingValue(Reg) + CSKY::R0_R1;
173981ad6265SDimitry Andric       return Match_Success;
174081ad6265SDimitry Andric     }
174181ad6265SDimitry Andric   }
174281ad6265SDimitry Andric 
174381ad6265SDimitry Andric   return Match_InvalidOperand;
174481ad6265SDimitry Andric }
1745fe6060f1SDimitry Andric 
17460eae32dcSDimitry Andric void CSKYAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
17470eae32dcSDimitry Andric   MCInst CInst;
17480eae32dcSDimitry Andric   bool Res = false;
17490eae32dcSDimitry Andric   if (EnableCompressedInst)
1750*bdd1243dSDimitry Andric     Res = compressInst(CInst, Inst, getSTI());
17510eae32dcSDimitry Andric   if (Res)
17520eae32dcSDimitry Andric     ++CSKYNumInstrsCompressed;
17530eae32dcSDimitry Andric   S.emitInstruction((Res ? CInst : Inst), getSTI());
17540eae32dcSDimitry Andric }
17550eae32dcSDimitry Andric 
1756fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser() {
1757fe6060f1SDimitry Andric   RegisterMCAsmParser<CSKYAsmParser> X(getTheCSKYTarget());
1758fe6060f1SDimitry Andric }
1759