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" 1606c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 17fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h" 1881ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 19fe6060f1SDimitry Andric #include "llvm/CodeGen/Register.h" 20fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h" 21fe6060f1SDimitry Andric #include "llvm/MC/MCExpr.h" 22fe6060f1SDimitry Andric #include "llvm/MC/MCInst.h" 2381ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 24fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 25fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 26fe6060f1SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h" 27fe6060f1SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 28349cc55cSDimitry Andric #include "llvm/MC/MCSectionELF.h" 29fe6060f1SDimitry Andric #include "llvm/MC/MCStreamer.h" 30fe6060f1SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 31349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 3281ad6265SDimitry Andric #include "llvm/Support/CSKYAttributes.h" 33fe6060f1SDimitry Andric #include "llvm/Support/Casting.h" 340eae32dcSDimitry Andric #include "llvm/Support/CommandLine.h" 35349cc55cSDimitry Andric #include "llvm/Support/Debug.h" 3606c3fb27SDimitry Andric #include "llvm/TargetParser/CSKYTargetParser.h" 37349cc55cSDimitry Andric 380eae32dcSDimitry Andric using namespace llvm; 390eae32dcSDimitry Andric 40349cc55cSDimitry Andric #define DEBUG_TYPE "csky-asm-parser" 41fe6060f1SDimitry Andric 420eae32dcSDimitry Andric // Include the auto-generated portion of the compress emitter. 430eae32dcSDimitry Andric #define GEN_COMPRESS_INSTR 440eae32dcSDimitry Andric #include "CSKYGenCompressInstEmitter.inc" 450eae32dcSDimitry Andric 460eae32dcSDimitry Andric STATISTIC(CSKYNumInstrsCompressed, 470eae32dcSDimitry Andric "Number of C-SKY Compressed instructions emitted"); 480eae32dcSDimitry Andric 490eae32dcSDimitry Andric static cl::opt<bool> 500eae32dcSDimitry Andric EnableCompressedInst("enable-csky-asm-compressed-inst", cl::Hidden, 510eae32dcSDimitry Andric cl::init(false), 520eae32dcSDimitry Andric cl::desc("Enable C-SKY asm compressed instruction")); 53fe6060f1SDimitry Andric 54fe6060f1SDimitry Andric namespace { 55fe6060f1SDimitry Andric struct CSKYOperand; 56fe6060f1SDimitry Andric 57fe6060f1SDimitry Andric class CSKYAsmParser : public MCTargetAsmParser { 58fe6060f1SDimitry Andric 59349cc55cSDimitry Andric const MCRegisterInfo *MRI; 60349cc55cSDimitry Andric 6181ad6265SDimitry Andric unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 6281ad6265SDimitry Andric unsigned Kind) override; 6381ad6265SDimitry Andric 64fe6060f1SDimitry Andric bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, 6506c3fb27SDimitry Andric int64_t Lower, int64_t Upper, 6606c3fb27SDimitry Andric const Twine &Msg); 67fe6060f1SDimitry Andric 68fe6060f1SDimitry Andric SMLoc getLoc() const { return getParser().getTok().getLoc(); } 69fe6060f1SDimitry Andric 70fe6060f1SDimitry Andric bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 71fe6060f1SDimitry Andric OperandVector &Operands, MCStreamer &Out, 72fe6060f1SDimitry Andric uint64_t &ErrorInfo, 73fe6060f1SDimitry Andric bool MatchingInlineAsm) override; 74fe6060f1SDimitry Andric 755f757f3fSDimitry Andric bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; 76fe6060f1SDimitry Andric 77fe6060f1SDimitry Andric bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 78fe6060f1SDimitry Andric SMLoc NameLoc, OperandVector &Operands) override; 79fe6060f1SDimitry Andric 8006c3fb27SDimitry Andric ParseStatus parseDirective(AsmToken DirectiveID) override; 81fe6060f1SDimitry Andric 820eae32dcSDimitry Andric // Helper to actually emit an instruction to the MCStreamer. Also, when 830eae32dcSDimitry Andric // possible, compression of the instruction is performed. 840eae32dcSDimitry Andric void emitToStreamer(MCStreamer &S, const MCInst &Inst); 850eae32dcSDimitry Andric 865f757f3fSDimitry Andric ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 87fe6060f1SDimitry Andric SMLoc &EndLoc) override; 88fe6060f1SDimitry Andric 89349cc55cSDimitry Andric bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, 90349cc55cSDimitry Andric MCStreamer &Out); 9181ad6265SDimitry Andric bool processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 9281ad6265SDimitry Andric bool processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 9381ad6265SDimitry Andric bool processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 9481ad6265SDimitry Andric 9581ad6265SDimitry Andric CSKYTargetStreamer &getTargetStreamer() { 9681ad6265SDimitry Andric assert(getParser().getStreamer().getTargetStreamer() && 9781ad6265SDimitry Andric "do not have a target streamer"); 9881ad6265SDimitry Andric MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 9981ad6265SDimitry Andric return static_cast<CSKYTargetStreamer &>(TS); 10081ad6265SDimitry Andric } 101349cc55cSDimitry Andric 102fe6060f1SDimitry Andric // Auto-generated instruction matching functions 103fe6060f1SDimitry Andric #define GET_ASSEMBLER_HEADER 104fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc" 105fe6060f1SDimitry Andric 10606c3fb27SDimitry Andric ParseStatus parseImmediate(OperandVector &Operands); 10706c3fb27SDimitry Andric ParseStatus parseRegister(OperandVector &Operands); 10806c3fb27SDimitry Andric ParseStatus parseBaseRegImm(OperandVector &Operands); 10906c3fb27SDimitry Andric ParseStatus parseCSKYSymbol(OperandVector &Operands); 11006c3fb27SDimitry Andric ParseStatus parseConstpoolSymbol(OperandVector &Operands); 11106c3fb27SDimitry Andric ParseStatus parseDataSymbol(OperandVector &Operands); 11206c3fb27SDimitry Andric ParseStatus parsePSRFlag(OperandVector &Operands); 11306c3fb27SDimitry Andric ParseStatus parseRegSeq(OperandVector &Operands); 11406c3fb27SDimitry Andric ParseStatus parseRegList(OperandVector &Operands); 115fe6060f1SDimitry Andric 116fe6060f1SDimitry Andric bool parseOperand(OperandVector &Operands, StringRef Mnemonic); 117fe6060f1SDimitry Andric 11881ad6265SDimitry Andric bool parseDirectiveAttribute(); 11981ad6265SDimitry Andric 120fe6060f1SDimitry Andric public: 121fe6060f1SDimitry Andric enum CSKYMatchResultTy { 122fe6060f1SDimitry Andric Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 123349cc55cSDimitry Andric Match_RequiresSameSrcAndDst, 124349cc55cSDimitry Andric Match_InvalidRegOutOfRange, 125fe6060f1SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES 126fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc" 127fe6060f1SDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES 128fe6060f1SDimitry Andric }; 129fe6060f1SDimitry Andric 130fe6060f1SDimitry Andric CSKYAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 131fe6060f1SDimitry Andric const MCInstrInfo &MII, const MCTargetOptions &Options) 132fe6060f1SDimitry Andric : MCTargetAsmParser(Options, STI, MII) { 13381ad6265SDimitry Andric 13481ad6265SDimitry Andric MCAsmParserExtension::Initialize(Parser); 13581ad6265SDimitry Andric 13681ad6265SDimitry Andric // Cache the MCRegisterInfo. 13781ad6265SDimitry Andric MRI = getContext().getRegisterInfo(); 13881ad6265SDimitry Andric 139fe6060f1SDimitry Andric setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 14081ad6265SDimitry Andric getTargetStreamer().emitTargetAttributes(STI); 141fe6060f1SDimitry Andric } 142fe6060f1SDimitry Andric }; 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric /// Instances of this class represent a parsed machine instruction. 145fe6060f1SDimitry Andric struct CSKYOperand : public MCParsedAsmOperand { 146349cc55cSDimitry Andric 147fe6060f1SDimitry Andric enum KindTy { 148fe6060f1SDimitry Andric Token, 149fe6060f1SDimitry Andric Register, 150fe6060f1SDimitry Andric Immediate, 151349cc55cSDimitry Andric RegisterSeq, 152349cc55cSDimitry Andric CPOP, 153349cc55cSDimitry Andric RegisterList 154fe6060f1SDimitry Andric } Kind; 155fe6060f1SDimitry Andric 156fe6060f1SDimitry Andric struct RegOp { 157fe6060f1SDimitry Andric unsigned RegNum; 158fe6060f1SDimitry Andric }; 159fe6060f1SDimitry Andric 160fe6060f1SDimitry Andric struct ImmOp { 161fe6060f1SDimitry Andric const MCExpr *Val; 162fe6060f1SDimitry Andric }; 163fe6060f1SDimitry Andric 164349cc55cSDimitry Andric struct ConstpoolOp { 165349cc55cSDimitry Andric const MCExpr *Val; 166349cc55cSDimitry Andric }; 167349cc55cSDimitry Andric 168349cc55cSDimitry Andric struct RegSeqOp { 169349cc55cSDimitry Andric unsigned RegNumFrom; 170349cc55cSDimitry Andric unsigned RegNumTo; 171349cc55cSDimitry Andric }; 172349cc55cSDimitry Andric 173349cc55cSDimitry Andric struct RegListOp { 174349cc55cSDimitry Andric unsigned List1From = 0; 175349cc55cSDimitry Andric unsigned List1To = 0; 176349cc55cSDimitry Andric unsigned List2From = 0; 177349cc55cSDimitry Andric unsigned List2To = 0; 178349cc55cSDimitry Andric unsigned List3From = 0; 179349cc55cSDimitry Andric unsigned List3To = 0; 180349cc55cSDimitry Andric unsigned List4From = 0; 181349cc55cSDimitry Andric unsigned List4To = 0; 182349cc55cSDimitry Andric }; 183349cc55cSDimitry Andric 184fe6060f1SDimitry Andric SMLoc StartLoc, EndLoc; 185fe6060f1SDimitry Andric union { 186fe6060f1SDimitry Andric StringRef Tok; 187fe6060f1SDimitry Andric RegOp Reg; 188fe6060f1SDimitry Andric ImmOp Imm; 189349cc55cSDimitry Andric ConstpoolOp CPool; 190349cc55cSDimitry Andric RegSeqOp RegSeq; 191349cc55cSDimitry Andric RegListOp RegList; 192fe6060f1SDimitry Andric }; 193fe6060f1SDimitry Andric 194fe6060f1SDimitry Andric CSKYOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 195fe6060f1SDimitry Andric 196fe6060f1SDimitry Andric public: 197fe6060f1SDimitry Andric CSKYOperand(const CSKYOperand &o) : MCParsedAsmOperand() { 198fe6060f1SDimitry Andric Kind = o.Kind; 199fe6060f1SDimitry Andric StartLoc = o.StartLoc; 200fe6060f1SDimitry Andric EndLoc = o.EndLoc; 201fe6060f1SDimitry Andric switch (Kind) { 202fe6060f1SDimitry Andric case Register: 203fe6060f1SDimitry Andric Reg = o.Reg; 204fe6060f1SDimitry Andric break; 205349cc55cSDimitry Andric case RegisterSeq: 206349cc55cSDimitry Andric RegSeq = o.RegSeq; 207349cc55cSDimitry Andric break; 208349cc55cSDimitry Andric case CPOP: 209349cc55cSDimitry Andric CPool = o.CPool; 210349cc55cSDimitry Andric break; 211fe6060f1SDimitry Andric case Immediate: 212fe6060f1SDimitry Andric Imm = o.Imm; 213fe6060f1SDimitry Andric break; 214fe6060f1SDimitry Andric case Token: 215fe6060f1SDimitry Andric Tok = o.Tok; 216fe6060f1SDimitry Andric break; 217349cc55cSDimitry Andric case RegisterList: 218349cc55cSDimitry Andric RegList = o.RegList; 219349cc55cSDimitry Andric break; 220fe6060f1SDimitry Andric } 221fe6060f1SDimitry Andric } 222fe6060f1SDimitry Andric 223fe6060f1SDimitry Andric bool isToken() const override { return Kind == Token; } 224fe6060f1SDimitry Andric bool isReg() const override { return Kind == Register; } 225fe6060f1SDimitry Andric bool isImm() const override { return Kind == Immediate; } 226349cc55cSDimitry Andric bool isRegisterSeq() const { return Kind == RegisterSeq; } 227349cc55cSDimitry Andric bool isRegisterList() const { return Kind == RegisterList; } 228349cc55cSDimitry Andric bool isConstPoolOp() const { return Kind == CPOP; } 229349cc55cSDimitry Andric 230fe6060f1SDimitry Andric bool isMem() const override { return false; } 231fe6060f1SDimitry Andric 232fe6060f1SDimitry Andric static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) { 233fe6060f1SDimitry Andric if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { 234fe6060f1SDimitry Andric Imm = CE->getValue(); 235fe6060f1SDimitry Andric return true; 236fe6060f1SDimitry Andric } 237fe6060f1SDimitry Andric 238fe6060f1SDimitry Andric return false; 239fe6060f1SDimitry Andric } 240fe6060f1SDimitry Andric 241fe6060f1SDimitry Andric template <unsigned num, unsigned shift = 0> bool isUImm() const { 242fe6060f1SDimitry Andric if (!isImm()) 243fe6060f1SDimitry Andric return false; 244fe6060f1SDimitry Andric 245fe6060f1SDimitry Andric int64_t Imm; 246fe6060f1SDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm); 247fe6060f1SDimitry Andric return IsConstantImm && isShiftedUInt<num, shift>(Imm); 248fe6060f1SDimitry Andric } 249fe6060f1SDimitry Andric 250fe6060f1SDimitry Andric template <unsigned num> bool isOImm() const { 251fe6060f1SDimitry Andric if (!isImm()) 252fe6060f1SDimitry Andric return false; 253fe6060f1SDimitry Andric 254fe6060f1SDimitry Andric int64_t Imm; 255fe6060f1SDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm); 256fe6060f1SDimitry Andric return IsConstantImm && isUInt<num>(Imm - 1); 257fe6060f1SDimitry Andric } 258fe6060f1SDimitry Andric 259fe6060f1SDimitry Andric template <unsigned num, unsigned shift = 0> bool isSImm() const { 260fe6060f1SDimitry Andric if (!isImm()) 261fe6060f1SDimitry Andric return false; 262fe6060f1SDimitry Andric 263fe6060f1SDimitry Andric int64_t Imm; 264fe6060f1SDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm); 265fe6060f1SDimitry Andric return IsConstantImm && isShiftedInt<num, shift>(Imm); 266fe6060f1SDimitry Andric } 267fe6060f1SDimitry Andric 268349cc55cSDimitry Andric bool isUImm1() const { return isUImm<1>(); } 269fe6060f1SDimitry Andric bool isUImm2() const { return isUImm<2>(); } 270349cc55cSDimitry Andric bool isUImm3() const { return isUImm<3>(); } 271349cc55cSDimitry Andric bool isUImm4() const { return isUImm<4>(); } 272fe6060f1SDimitry Andric bool isUImm5() const { return isUImm<5>(); } 273349cc55cSDimitry Andric bool isUImm6() const { return isUImm<6>(); } 274349cc55cSDimitry Andric bool isUImm7() const { return isUImm<7>(); } 275349cc55cSDimitry Andric bool isUImm8() const { return isUImm<8>(); } 276fe6060f1SDimitry Andric bool isUImm12() const { return isUImm<12>(); } 277fe6060f1SDimitry Andric bool isUImm16() const { return isUImm<16>(); } 278349cc55cSDimitry Andric bool isUImm20() const { return isUImm<20>(); } 279349cc55cSDimitry Andric bool isUImm24() const { return isUImm<24>(); } 280fe6060f1SDimitry Andric 281349cc55cSDimitry Andric bool isOImm3() const { return isOImm<3>(); } 282349cc55cSDimitry Andric bool isOImm4() const { return isOImm<4>(); } 283349cc55cSDimitry Andric bool isOImm5() const { return isOImm<5>(); } 284349cc55cSDimitry Andric bool isOImm6() const { return isOImm<6>(); } 285349cc55cSDimitry Andric bool isOImm8() const { return isOImm<8>(); } 286fe6060f1SDimitry Andric bool isOImm12() const { return isOImm<12>(); } 287fe6060f1SDimitry Andric bool isOImm16() const { return isOImm<16>(); } 288fe6060f1SDimitry Andric 289349cc55cSDimitry Andric bool isSImm8() const { return isSImm<8>(); } 290349cc55cSDimitry Andric 291349cc55cSDimitry Andric bool isUImm5Shift1() { return isUImm<5, 1>(); } 292349cc55cSDimitry Andric bool isUImm5Shift2() { return isUImm<5, 2>(); } 293349cc55cSDimitry Andric bool isUImm7Shift1() { return isUImm<7, 1>(); } 294349cc55cSDimitry Andric bool isUImm7Shift2() { return isUImm<7, 2>(); } 295349cc55cSDimitry Andric bool isUImm7Shift3() { return isUImm<7, 3>(); } 296349cc55cSDimitry Andric bool isUImm8Shift2() { return isUImm<8, 2>(); } 297349cc55cSDimitry Andric bool isUImm8Shift3() { return isUImm<8, 3>(); } 298349cc55cSDimitry Andric bool isUImm8Shift8() { return isUImm<8, 8>(); } 299349cc55cSDimitry Andric bool isUImm8Shift16() { return isUImm<8, 16>(); } 300349cc55cSDimitry Andric bool isUImm8Shift24() { return isUImm<8, 24>(); } 301fe6060f1SDimitry Andric bool isUImm12Shift1() { return isUImm<12, 1>(); } 302fe6060f1SDimitry Andric bool isUImm12Shift2() { return isUImm<12, 2>(); } 303349cc55cSDimitry Andric bool isUImm16Shift8() { return isUImm<16, 8>(); } 304349cc55cSDimitry Andric bool isUImm16Shift16() { return isUImm<16, 16>(); } 305349cc55cSDimitry Andric bool isUImm24Shift8() { return isUImm<24, 8>(); } 306fe6060f1SDimitry Andric 307fe6060f1SDimitry Andric bool isSImm16Shift1() { return isSImm<16, 1>(); } 308fe6060f1SDimitry Andric 309349cc55cSDimitry Andric bool isCSKYSymbol() const { return isImm(); } 310349cc55cSDimitry Andric 311349cc55cSDimitry Andric bool isConstpool() const { return isConstPoolOp(); } 312349cc55cSDimitry Andric bool isDataSymbol() const { return isConstPoolOp(); } 313349cc55cSDimitry Andric 314349cc55cSDimitry Andric bool isPSRFlag() const { 315fe6060f1SDimitry Andric int64_t Imm; 316349cc55cSDimitry Andric // Must be of 'immediate' type and a constant. 317349cc55cSDimitry Andric if (!isImm() || !evaluateConstantImm(getImm(), Imm)) 318349cc55cSDimitry Andric return false; 319349cc55cSDimitry Andric 320349cc55cSDimitry Andric return isUInt<5>(Imm); 321349cc55cSDimitry Andric } 322349cc55cSDimitry Andric 323349cc55cSDimitry Andric template <unsigned MIN, unsigned MAX> bool isRegSeqTemplate() const { 324349cc55cSDimitry Andric if (!isRegisterSeq()) 325349cc55cSDimitry Andric return false; 326349cc55cSDimitry Andric 327349cc55cSDimitry Andric std::pair<unsigned, unsigned> regSeq = getRegSeq(); 328349cc55cSDimitry Andric 329349cc55cSDimitry Andric return MIN <= regSeq.first && regSeq.first <= regSeq.second && 330349cc55cSDimitry Andric regSeq.second <= MAX; 331349cc55cSDimitry Andric } 332349cc55cSDimitry Andric 333349cc55cSDimitry Andric bool isRegSeq() const { return isRegSeqTemplate<CSKY::R0, CSKY::R31>(); } 334349cc55cSDimitry Andric 33504eeddc0SDimitry Andric bool isRegSeqV1() const { 33604eeddc0SDimitry Andric return isRegSeqTemplate<CSKY::F0_32, CSKY::F15_32>(); 33704eeddc0SDimitry Andric } 33804eeddc0SDimitry Andric 33904eeddc0SDimitry Andric bool isRegSeqV2() const { 34004eeddc0SDimitry Andric return isRegSeqTemplate<CSKY::F0_32, CSKY::F31_32>(); 34104eeddc0SDimitry Andric } 34204eeddc0SDimitry Andric 343349cc55cSDimitry Andric static bool isLegalRegList(unsigned from, unsigned to) { 344349cc55cSDimitry Andric if (from == 0 && to == 0) 345349cc55cSDimitry Andric return true; 346349cc55cSDimitry Andric 347349cc55cSDimitry Andric if (from == to) { 348349cc55cSDimitry Andric if (from != CSKY::R4 && from != CSKY::R15 && from != CSKY::R16 && 349349cc55cSDimitry Andric from != CSKY::R28) 350349cc55cSDimitry Andric return false; 351349cc55cSDimitry Andric 352349cc55cSDimitry Andric return true; 353349cc55cSDimitry Andric } else { 354349cc55cSDimitry Andric if (from != CSKY::R4 && from != CSKY::R16) 355349cc55cSDimitry Andric return false; 356349cc55cSDimitry Andric 357349cc55cSDimitry Andric if (from == CSKY::R4 && to > CSKY::R4 && to < CSKY::R12) 358349cc55cSDimitry Andric return true; 359349cc55cSDimitry Andric else if (from == CSKY::R16 && to > CSKY::R16 && to < CSKY::R18) 360349cc55cSDimitry Andric return true; 361349cc55cSDimitry Andric else 362349cc55cSDimitry Andric return false; 363349cc55cSDimitry Andric } 364349cc55cSDimitry Andric } 365349cc55cSDimitry Andric 366349cc55cSDimitry Andric bool isRegList() const { 367349cc55cSDimitry Andric if (!isRegisterList()) 368349cc55cSDimitry Andric return false; 369349cc55cSDimitry Andric 370349cc55cSDimitry Andric auto regList = getRegList(); 371349cc55cSDimitry Andric 372349cc55cSDimitry Andric if (!isLegalRegList(regList.List1From, regList.List1To)) 373349cc55cSDimitry Andric return false; 374349cc55cSDimitry Andric if (!isLegalRegList(regList.List2From, regList.List2To)) 375349cc55cSDimitry Andric return false; 376349cc55cSDimitry Andric if (!isLegalRegList(regList.List3From, regList.List3To)) 377349cc55cSDimitry Andric return false; 378349cc55cSDimitry Andric if (!isLegalRegList(regList.List4From, regList.List4To)) 379349cc55cSDimitry Andric return false; 380349cc55cSDimitry Andric 381349cc55cSDimitry Andric return true; 382349cc55cSDimitry Andric } 383349cc55cSDimitry Andric 384349cc55cSDimitry Andric bool isExtImm6() { 385349cc55cSDimitry Andric if (!isImm()) 386349cc55cSDimitry Andric return false; 387349cc55cSDimitry Andric 388349cc55cSDimitry Andric int64_t Imm; 389349cc55cSDimitry Andric bool IsConstantImm = evaluateConstantImm(getImm(), Imm); 390349cc55cSDimitry Andric if (!IsConstantImm) 391349cc55cSDimitry Andric return false; 392349cc55cSDimitry Andric 393349cc55cSDimitry Andric int uimm4 = Imm & 0xf; 394349cc55cSDimitry Andric 395349cc55cSDimitry Andric return isShiftedUInt<6, 0>(Imm) && uimm4 >= 0 && uimm4 <= 14; 396fe6060f1SDimitry Andric } 397fe6060f1SDimitry Andric 398fe6060f1SDimitry Andric /// Gets location of the first token of this operand. 399fe6060f1SDimitry Andric SMLoc getStartLoc() const override { return StartLoc; } 400fe6060f1SDimitry Andric /// Gets location of the last token of this operand. 401fe6060f1SDimitry Andric SMLoc getEndLoc() const override { return EndLoc; } 402fe6060f1SDimitry Andric 403*0fca6ea1SDimitry Andric MCRegister getReg() const override { 404fe6060f1SDimitry Andric assert(Kind == Register && "Invalid type access!"); 405fe6060f1SDimitry Andric return Reg.RegNum; 406fe6060f1SDimitry Andric } 407fe6060f1SDimitry Andric 408349cc55cSDimitry Andric std::pair<unsigned, unsigned> getRegSeq() const { 409349cc55cSDimitry Andric assert(Kind == RegisterSeq && "Invalid type access!"); 410349cc55cSDimitry Andric return std::pair<unsigned, unsigned>(RegSeq.RegNumFrom, RegSeq.RegNumTo); 411349cc55cSDimitry Andric } 412349cc55cSDimitry Andric 413349cc55cSDimitry Andric RegListOp getRegList() const { 414349cc55cSDimitry Andric assert(Kind == RegisterList && "Invalid type access!"); 415349cc55cSDimitry Andric return RegList; 416349cc55cSDimitry Andric } 417349cc55cSDimitry Andric 418fe6060f1SDimitry Andric const MCExpr *getImm() const { 419fe6060f1SDimitry Andric assert(Kind == Immediate && "Invalid type access!"); 420fe6060f1SDimitry Andric return Imm.Val; 421fe6060f1SDimitry Andric } 422fe6060f1SDimitry Andric 423349cc55cSDimitry Andric const MCExpr *getConstpoolOp() const { 424349cc55cSDimitry Andric assert(Kind == CPOP && "Invalid type access!"); 425349cc55cSDimitry Andric return CPool.Val; 426349cc55cSDimitry Andric } 427349cc55cSDimitry Andric 428fe6060f1SDimitry Andric StringRef getToken() const { 429fe6060f1SDimitry Andric assert(Kind == Token && "Invalid type access!"); 430fe6060f1SDimitry Andric return Tok; 431fe6060f1SDimitry Andric } 432fe6060f1SDimitry Andric 433fe6060f1SDimitry Andric void print(raw_ostream &OS) const override { 434bdd1243dSDimitry Andric auto RegName = [](MCRegister Reg) { 435349cc55cSDimitry Andric if (Reg) 436349cc55cSDimitry Andric return CSKYInstPrinter::getRegisterName(Reg); 437349cc55cSDimitry Andric else 438349cc55cSDimitry Andric return "noreg"; 439349cc55cSDimitry Andric }; 440349cc55cSDimitry Andric 441fe6060f1SDimitry Andric switch (Kind) { 442349cc55cSDimitry Andric case CPOP: 443349cc55cSDimitry Andric OS << *getConstpoolOp(); 444349cc55cSDimitry Andric break; 445fe6060f1SDimitry Andric case Immediate: 446fe6060f1SDimitry Andric OS << *getImm(); 447fe6060f1SDimitry Andric break; 448349cc55cSDimitry Andric case KindTy::Register: 449349cc55cSDimitry Andric OS << "<register " << RegName(getReg()) << ">"; 450349cc55cSDimitry Andric break; 451349cc55cSDimitry Andric case RegisterSeq: 452349cc55cSDimitry Andric OS << "<register-seq "; 453349cc55cSDimitry Andric OS << RegName(getRegSeq().first) << "-" << RegName(getRegSeq().second) 454349cc55cSDimitry Andric << ">"; 455349cc55cSDimitry Andric break; 456349cc55cSDimitry Andric case RegisterList: 457349cc55cSDimitry Andric OS << "<register-list "; 458349cc55cSDimitry Andric OS << RegName(getRegList().List1From) << "-" 459349cc55cSDimitry Andric << RegName(getRegList().List1To) << ","; 460349cc55cSDimitry Andric OS << RegName(getRegList().List2From) << "-" 461349cc55cSDimitry Andric << RegName(getRegList().List2To) << ","; 462349cc55cSDimitry Andric OS << RegName(getRegList().List3From) << "-" 463349cc55cSDimitry Andric << RegName(getRegList().List3To) << ","; 464349cc55cSDimitry Andric OS << RegName(getRegList().List4From) << "-" 465349cc55cSDimitry Andric << RegName(getRegList().List4To); 466fe6060f1SDimitry Andric break; 467fe6060f1SDimitry Andric case Token: 468fe6060f1SDimitry Andric OS << "'" << getToken() << "'"; 469fe6060f1SDimitry Andric break; 470fe6060f1SDimitry Andric } 471fe6060f1SDimitry Andric } 472fe6060f1SDimitry Andric 473fe6060f1SDimitry Andric static std::unique_ptr<CSKYOperand> createToken(StringRef Str, SMLoc S) { 474fe6060f1SDimitry Andric auto Op = std::make_unique<CSKYOperand>(Token); 475fe6060f1SDimitry Andric Op->Tok = Str; 476fe6060f1SDimitry Andric Op->StartLoc = S; 477fe6060f1SDimitry Andric Op->EndLoc = S; 478fe6060f1SDimitry Andric return Op; 479fe6060f1SDimitry Andric } 480fe6060f1SDimitry Andric 481fe6060f1SDimitry Andric static std::unique_ptr<CSKYOperand> createReg(unsigned RegNo, SMLoc S, 482fe6060f1SDimitry Andric SMLoc E) { 483fe6060f1SDimitry Andric auto Op = std::make_unique<CSKYOperand>(Register); 484fe6060f1SDimitry Andric Op->Reg.RegNum = RegNo; 485fe6060f1SDimitry Andric Op->StartLoc = S; 486fe6060f1SDimitry Andric Op->EndLoc = E; 487fe6060f1SDimitry Andric return Op; 488fe6060f1SDimitry Andric } 489fe6060f1SDimitry Andric 490349cc55cSDimitry Andric static std::unique_ptr<CSKYOperand> createRegSeq(unsigned RegNoFrom, 491349cc55cSDimitry Andric unsigned RegNoTo, SMLoc S) { 492349cc55cSDimitry Andric auto Op = std::make_unique<CSKYOperand>(RegisterSeq); 493349cc55cSDimitry Andric Op->RegSeq.RegNumFrom = RegNoFrom; 494349cc55cSDimitry Andric Op->RegSeq.RegNumTo = RegNoTo; 495349cc55cSDimitry Andric Op->StartLoc = S; 496349cc55cSDimitry Andric Op->EndLoc = S; 497349cc55cSDimitry Andric return Op; 498349cc55cSDimitry Andric } 499349cc55cSDimitry Andric 500349cc55cSDimitry Andric static std::unique_ptr<CSKYOperand> 501349cc55cSDimitry Andric createRegList(SmallVector<unsigned, 4> reglist, SMLoc S) { 502349cc55cSDimitry Andric auto Op = std::make_unique<CSKYOperand>(RegisterList); 503349cc55cSDimitry Andric Op->RegList.List1From = 0; 504349cc55cSDimitry Andric Op->RegList.List1To = 0; 505349cc55cSDimitry Andric Op->RegList.List2From = 0; 506349cc55cSDimitry Andric Op->RegList.List2To = 0; 507349cc55cSDimitry Andric Op->RegList.List3From = 0; 508349cc55cSDimitry Andric Op->RegList.List3To = 0; 509349cc55cSDimitry Andric Op->RegList.List4From = 0; 510349cc55cSDimitry Andric Op->RegList.List4To = 0; 511349cc55cSDimitry Andric 512349cc55cSDimitry Andric for (unsigned i = 0; i < reglist.size(); i += 2) { 513349cc55cSDimitry Andric if (Op->RegList.List1From == 0) { 514349cc55cSDimitry Andric Op->RegList.List1From = reglist[i]; 515349cc55cSDimitry Andric Op->RegList.List1To = reglist[i + 1]; 516349cc55cSDimitry Andric } else if (Op->RegList.List2From == 0) { 517349cc55cSDimitry Andric Op->RegList.List2From = reglist[i]; 518349cc55cSDimitry Andric Op->RegList.List2To = reglist[i + 1]; 519349cc55cSDimitry Andric } else if (Op->RegList.List3From == 0) { 520349cc55cSDimitry Andric Op->RegList.List3From = reglist[i]; 521349cc55cSDimitry Andric Op->RegList.List3To = reglist[i + 1]; 522349cc55cSDimitry Andric } else if (Op->RegList.List4From == 0) { 523349cc55cSDimitry Andric Op->RegList.List4From = reglist[i]; 524349cc55cSDimitry Andric Op->RegList.List4To = reglist[i + 1]; 525349cc55cSDimitry Andric } else { 526349cc55cSDimitry Andric assert(0); 527349cc55cSDimitry Andric } 528349cc55cSDimitry Andric } 529349cc55cSDimitry Andric 530349cc55cSDimitry Andric Op->StartLoc = S; 531349cc55cSDimitry Andric Op->EndLoc = S; 532349cc55cSDimitry Andric return Op; 533349cc55cSDimitry Andric } 534349cc55cSDimitry Andric 535fe6060f1SDimitry Andric static std::unique_ptr<CSKYOperand> createImm(const MCExpr *Val, SMLoc S, 536fe6060f1SDimitry Andric SMLoc E) { 537fe6060f1SDimitry Andric auto Op = std::make_unique<CSKYOperand>(Immediate); 538fe6060f1SDimitry Andric Op->Imm.Val = Val; 539fe6060f1SDimitry Andric Op->StartLoc = S; 540fe6060f1SDimitry Andric Op->EndLoc = E; 541fe6060f1SDimitry Andric return Op; 542fe6060f1SDimitry Andric } 543fe6060f1SDimitry Andric 544349cc55cSDimitry Andric static std::unique_ptr<CSKYOperand> createConstpoolOp(const MCExpr *Val, 545349cc55cSDimitry Andric SMLoc S, SMLoc E) { 546349cc55cSDimitry Andric auto Op = std::make_unique<CSKYOperand>(CPOP); 547349cc55cSDimitry Andric Op->CPool.Val = Val; 548349cc55cSDimitry Andric Op->StartLoc = S; 549349cc55cSDimitry Andric Op->EndLoc = E; 550349cc55cSDimitry Andric return Op; 551349cc55cSDimitry Andric } 552349cc55cSDimitry Andric 553fe6060f1SDimitry Andric void addExpr(MCInst &Inst, const MCExpr *Expr) const { 554fe6060f1SDimitry Andric assert(Expr && "Expr shouldn't be null!"); 555fe6060f1SDimitry Andric if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) 556fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createImm(CE->getValue())); 557fe6060f1SDimitry Andric else 558fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 559fe6060f1SDimitry Andric } 560fe6060f1SDimitry Andric 561fe6060f1SDimitry Andric // Used by the TableGen Code. 562fe6060f1SDimitry Andric void addRegOperands(MCInst &Inst, unsigned N) const { 563fe6060f1SDimitry Andric assert(N == 1 && "Invalid number of operands!"); 564fe6060f1SDimitry Andric Inst.addOperand(MCOperand::createReg(getReg())); 565fe6060f1SDimitry Andric } 566fe6060f1SDimitry Andric 567fe6060f1SDimitry Andric void addImmOperands(MCInst &Inst, unsigned N) const { 568fe6060f1SDimitry Andric assert(N == 1 && "Invalid number of operands!"); 569fe6060f1SDimitry Andric addExpr(Inst, getImm()); 570fe6060f1SDimitry Andric } 571349cc55cSDimitry Andric 572349cc55cSDimitry Andric void addConstpoolOperands(MCInst &Inst, unsigned N) const { 573349cc55cSDimitry Andric assert(N == 1 && "Invalid number of operands!"); 574349cc55cSDimitry Andric Inst.addOperand(MCOperand::createExpr(getConstpoolOp())); 575349cc55cSDimitry Andric } 576349cc55cSDimitry Andric 577349cc55cSDimitry Andric void addRegSeqOperands(MCInst &Inst, unsigned N) const { 578349cc55cSDimitry Andric assert(N == 2 && "Invalid number of operands!"); 579349cc55cSDimitry Andric auto regSeq = getRegSeq(); 580349cc55cSDimitry Andric 581349cc55cSDimitry Andric Inst.addOperand(MCOperand::createReg(regSeq.first)); 582349cc55cSDimitry Andric Inst.addOperand(MCOperand::createReg(regSeq.second)); 583349cc55cSDimitry Andric } 584349cc55cSDimitry Andric 585349cc55cSDimitry Andric static unsigned getListValue(unsigned ListFrom, unsigned ListTo) { 586349cc55cSDimitry Andric if (ListFrom == ListTo && ListFrom == CSKY::R15) 587349cc55cSDimitry Andric return (1 << 4); 588349cc55cSDimitry Andric else if (ListFrom == ListTo && ListFrom == CSKY::R28) 589349cc55cSDimitry Andric return (1 << 8); 590349cc55cSDimitry Andric else if (ListFrom == CSKY::R4) 591349cc55cSDimitry Andric return ListTo - ListFrom + 1; 592349cc55cSDimitry Andric else if (ListFrom == CSKY::R16) 593349cc55cSDimitry Andric return ((ListTo - ListFrom + 1) << 5); 594349cc55cSDimitry Andric else 595349cc55cSDimitry Andric return 0; 596349cc55cSDimitry Andric } 597349cc55cSDimitry Andric 598349cc55cSDimitry Andric void addRegListOperands(MCInst &Inst, unsigned N) const { 599349cc55cSDimitry Andric assert(N == 1 && "Invalid number of operands!"); 600349cc55cSDimitry Andric auto regList = getRegList(); 601349cc55cSDimitry Andric 602349cc55cSDimitry Andric unsigned V = 0; 603349cc55cSDimitry Andric 604349cc55cSDimitry Andric unsigned T = getListValue(regList.List1From, regList.List1To); 605349cc55cSDimitry Andric if (T != 0) 606349cc55cSDimitry Andric V = V | T; 607349cc55cSDimitry Andric 608349cc55cSDimitry Andric T = getListValue(regList.List2From, regList.List2To); 609349cc55cSDimitry Andric if (T != 0) 610349cc55cSDimitry Andric V = V | T; 611349cc55cSDimitry Andric 612349cc55cSDimitry Andric T = getListValue(regList.List3From, regList.List3To); 613349cc55cSDimitry Andric if (T != 0) 614349cc55cSDimitry Andric V = V | T; 615349cc55cSDimitry Andric 616349cc55cSDimitry Andric T = getListValue(regList.List4From, regList.List4To); 617349cc55cSDimitry Andric if (T != 0) 618349cc55cSDimitry Andric V = V | T; 619349cc55cSDimitry Andric 620349cc55cSDimitry Andric Inst.addOperand(MCOperand::createImm(V)); 621349cc55cSDimitry Andric } 622349cc55cSDimitry Andric 623349cc55cSDimitry Andric bool isValidForTie(const CSKYOperand &Other) const { 624349cc55cSDimitry Andric if (Kind != Other.Kind) 625349cc55cSDimitry Andric return false; 626349cc55cSDimitry Andric 627349cc55cSDimitry Andric switch (Kind) { 628349cc55cSDimitry Andric default: 629349cc55cSDimitry Andric llvm_unreachable("Unexpected kind"); 630349cc55cSDimitry Andric return false; 631349cc55cSDimitry Andric case Register: 632349cc55cSDimitry Andric return Reg.RegNum == Other.Reg.RegNum; 633349cc55cSDimitry Andric } 634349cc55cSDimitry Andric } 635fe6060f1SDimitry Andric }; 636fe6060f1SDimitry Andric } // end anonymous namespace. 637fe6060f1SDimitry Andric 638fe6060f1SDimitry Andric #define GET_REGISTER_MATCHER 639fe6060f1SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME 640fe6060f1SDimitry Andric #define GET_MATCHER_IMPLEMENTATION 641fe6060f1SDimitry Andric #define GET_MNEMONIC_SPELL_CHECKER 642fe6060f1SDimitry Andric #include "CSKYGenAsmMatcher.inc" 643fe6060f1SDimitry Andric 64481ad6265SDimitry Andric static MCRegister convertFPR32ToFPR64(MCRegister Reg) { 64581ad6265SDimitry Andric assert(Reg >= CSKY::F0_32 && Reg <= CSKY::F31_32 && "Invalid register"); 64681ad6265SDimitry Andric return Reg - CSKY::F0_32 + CSKY::F0_64; 64781ad6265SDimitry Andric } 64881ad6265SDimitry Andric 649fe6060f1SDimitry Andric static std::string CSKYMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, 650fe6060f1SDimitry Andric unsigned VariantID = 0); 651fe6060f1SDimitry Andric 652fe6060f1SDimitry Andric bool CSKYAsmParser::generateImmOutOfRangeError( 653fe6060f1SDimitry Andric OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, 65406c3fb27SDimitry Andric const Twine &Msg = "immediate must be an integer in the range") { 655fe6060f1SDimitry Andric SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 656fe6060f1SDimitry Andric return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 657fe6060f1SDimitry Andric } 658fe6060f1SDimitry Andric 659fe6060f1SDimitry Andric bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 660fe6060f1SDimitry Andric OperandVector &Operands, 661fe6060f1SDimitry Andric MCStreamer &Out, 662fe6060f1SDimitry Andric uint64_t &ErrorInfo, 663fe6060f1SDimitry Andric bool MatchingInlineAsm) { 664fe6060f1SDimitry Andric MCInst Inst; 665fe6060f1SDimitry Andric FeatureBitset MissingFeatures; 666fe6060f1SDimitry Andric 667fe6060f1SDimitry Andric auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, 668fe6060f1SDimitry Andric MatchingInlineAsm); 669fe6060f1SDimitry Andric switch (Result) { 670fe6060f1SDimitry Andric default: 671fe6060f1SDimitry Andric break; 672fe6060f1SDimitry Andric case Match_Success: 673349cc55cSDimitry Andric return processInstruction(Inst, IDLoc, Operands, Out); 674fe6060f1SDimitry Andric case Match_MissingFeature: { 675fe6060f1SDimitry Andric assert(MissingFeatures.any() && "Unknown missing features!"); 676fe6060f1SDimitry Andric ListSeparator LS; 677fe6060f1SDimitry Andric std::string Msg = "instruction requires the following: "; 678fe6060f1SDimitry Andric for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { 679fe6060f1SDimitry Andric if (MissingFeatures[i]) { 680fe6060f1SDimitry Andric Msg += LS; 681fe6060f1SDimitry Andric Msg += getSubtargetFeatureName(i); 682fe6060f1SDimitry Andric } 683fe6060f1SDimitry Andric } 684fe6060f1SDimitry Andric return Error(IDLoc, Msg); 685fe6060f1SDimitry Andric } 686fe6060f1SDimitry Andric case Match_MnemonicFail: { 687fe6060f1SDimitry Andric FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 688fe6060f1SDimitry Andric std::string Suggestion = 689fe6060f1SDimitry Andric CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS); 690fe6060f1SDimitry Andric return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); 691fe6060f1SDimitry Andric } 692fe6060f1SDimitry Andric case Match_InvalidTiedOperand: 693fe6060f1SDimitry Andric case Match_InvalidOperand: { 694fe6060f1SDimitry Andric SMLoc ErrorLoc = IDLoc; 695fe6060f1SDimitry Andric if (ErrorInfo != ~0U) { 696fe6060f1SDimitry Andric if (ErrorInfo >= Operands.size()) 697fe6060f1SDimitry Andric return Error(ErrorLoc, "too few operands for instruction"); 698fe6060f1SDimitry Andric 699fe6060f1SDimitry Andric ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 700fe6060f1SDimitry Andric if (ErrorLoc == SMLoc()) 701fe6060f1SDimitry Andric ErrorLoc = IDLoc; 702fe6060f1SDimitry Andric } 703fe6060f1SDimitry Andric return Error(ErrorLoc, "invalid operand for instruction"); 704fe6060f1SDimitry Andric } 705fe6060f1SDimitry Andric } 706fe6060f1SDimitry Andric 707fe6060f1SDimitry Andric // Handle the case when the error message is of specific type 708fe6060f1SDimitry Andric // other than the generic Match_InvalidOperand, and the 709fe6060f1SDimitry Andric // corresponding operand is missing. 710fe6060f1SDimitry Andric if (Result > FIRST_TARGET_MATCH_RESULT_TY) { 711fe6060f1SDimitry Andric SMLoc ErrorLoc = IDLoc; 712fe6060f1SDimitry Andric if (ErrorInfo != ~0U && ErrorInfo >= Operands.size()) 713fe6060f1SDimitry Andric return Error(ErrorLoc, "too few operands for instruction"); 714fe6060f1SDimitry Andric } 715fe6060f1SDimitry Andric 716fe6060f1SDimitry Andric switch (Result) { 717fe6060f1SDimitry Andric default: 718fe6060f1SDimitry Andric break; 719349cc55cSDimitry Andric case Match_InvalidSImm8: 720349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 7), 721349cc55cSDimitry Andric (1 << 7) - 1); 722349cc55cSDimitry Andric case Match_InvalidOImm3: 723349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 3)); 724349cc55cSDimitry Andric case Match_InvalidOImm4: 725349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 4)); 726349cc55cSDimitry Andric case Match_InvalidOImm5: 727349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5)); 728349cc55cSDimitry Andric case Match_InvalidOImm6: 729349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6)); 730349cc55cSDimitry Andric case Match_InvalidOImm8: 731349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 8)); 732fe6060f1SDimitry Andric case Match_InvalidOImm12: 733fe6060f1SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12)); 734fe6060f1SDimitry Andric case Match_InvalidOImm16: 735fe6060f1SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16)); 736349cc55cSDimitry Andric case Match_InvalidUImm1: 737349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1); 738fe6060f1SDimitry Andric case Match_InvalidUImm2: 739fe6060f1SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1); 740349cc55cSDimitry Andric case Match_InvalidUImm3: 741349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1); 742349cc55cSDimitry Andric case Match_InvalidUImm4: 743349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1); 744fe6060f1SDimitry Andric case Match_InvalidUImm5: 745fe6060f1SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); 746349cc55cSDimitry Andric case Match_InvalidUImm6: 747349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1); 748349cc55cSDimitry Andric case Match_InvalidUImm7: 749349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1); 750349cc55cSDimitry Andric case Match_InvalidUImm8: 751349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1); 752fe6060f1SDimitry Andric case Match_InvalidUImm12: 753fe6060f1SDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1); 754349cc55cSDimitry Andric case Match_InvalidUImm16: 755349cc55cSDimitry Andric return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1); 756349cc55cSDimitry Andric case Match_InvalidUImm5Shift1: 757349cc55cSDimitry Andric return generateImmOutOfRangeError( 758349cc55cSDimitry Andric Operands, ErrorInfo, 0, (1 << 5) - 2, 759349cc55cSDimitry Andric "immediate must be a multiple of 2 bytes in the range"); 760fe6060f1SDimitry Andric case Match_InvalidUImm12Shift1: 761fe6060f1SDimitry Andric return generateImmOutOfRangeError( 762fe6060f1SDimitry Andric Operands, ErrorInfo, 0, (1 << 12) - 2, 763fe6060f1SDimitry Andric "immediate must be a multiple of 2 bytes in the range"); 764349cc55cSDimitry Andric case Match_InvalidUImm5Shift2: 765349cc55cSDimitry Andric return generateImmOutOfRangeError( 766349cc55cSDimitry Andric Operands, ErrorInfo, 0, (1 << 5) - 4, 767349cc55cSDimitry Andric "immediate must be a multiple of 4 bytes in the range"); 768349cc55cSDimitry Andric case Match_InvalidUImm7Shift1: 769349cc55cSDimitry Andric return generateImmOutOfRangeError( 770349cc55cSDimitry Andric Operands, ErrorInfo, 0, (1 << 7) - 2, 771349cc55cSDimitry Andric "immediate must be a multiple of 2 bytes in the range"); 772349cc55cSDimitry Andric case Match_InvalidUImm7Shift2: 773349cc55cSDimitry Andric return generateImmOutOfRangeError( 774349cc55cSDimitry Andric Operands, ErrorInfo, 0, (1 << 7) - 4, 775349cc55cSDimitry Andric "immediate must be a multiple of 4 bytes in the range"); 776349cc55cSDimitry Andric case Match_InvalidUImm8Shift2: 777349cc55cSDimitry Andric return generateImmOutOfRangeError( 778349cc55cSDimitry Andric Operands, ErrorInfo, 0, (1 << 8) - 4, 779349cc55cSDimitry Andric "immediate must be a multiple of 4 bytes in the range"); 780349cc55cSDimitry Andric case Match_InvalidUImm8Shift3: 781349cc55cSDimitry Andric return generateImmOutOfRangeError( 782349cc55cSDimitry Andric Operands, ErrorInfo, 0, (1 << 8) - 8, 783349cc55cSDimitry Andric "immediate must be a multiple of 8 bytes in the range"); 784349cc55cSDimitry Andric case Match_InvalidUImm8Shift8: 785349cc55cSDimitry Andric return generateImmOutOfRangeError( 786349cc55cSDimitry Andric Operands, ErrorInfo, 0, (1 << 8) - 256, 787349cc55cSDimitry Andric "immediate must be a multiple of 256 bytes in the range"); 788fe6060f1SDimitry Andric case Match_InvalidUImm12Shift2: 789fe6060f1SDimitry Andric return generateImmOutOfRangeError( 790fe6060f1SDimitry Andric Operands, ErrorInfo, 0, (1 << 12) - 4, 791fe6060f1SDimitry Andric "immediate must be a multiple of 4 bytes in the range"); 792fe6060f1SDimitry Andric case Match_InvalidCSKYSymbol: { 793fe6060f1SDimitry Andric SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 794fe6060f1SDimitry Andric return Error(ErrorLoc, "operand must be a symbol name"); 795fe6060f1SDimitry Andric } 796fe6060f1SDimitry Andric case Match_InvalidConstpool: { 797fe6060f1SDimitry Andric SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 798fe6060f1SDimitry Andric return Error(ErrorLoc, "operand must be a constpool symbol name"); 799fe6060f1SDimitry Andric } 800349cc55cSDimitry Andric case Match_InvalidPSRFlag: { 801349cc55cSDimitry Andric SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 802349cc55cSDimitry Andric return Error(ErrorLoc, "psrset operand is not valid"); 803349cc55cSDimitry Andric } 804349cc55cSDimitry Andric case Match_InvalidRegSeq: { 805349cc55cSDimitry Andric SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 806349cc55cSDimitry Andric return Error(ErrorLoc, "Register sequence is not valid"); 807349cc55cSDimitry Andric } 808349cc55cSDimitry Andric case Match_InvalidRegOutOfRange: { 809349cc55cSDimitry Andric SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 810349cc55cSDimitry Andric return Error(ErrorLoc, "register is out of range"); 811349cc55cSDimitry Andric } 812349cc55cSDimitry Andric case Match_RequiresSameSrcAndDst: { 813349cc55cSDimitry Andric SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 814349cc55cSDimitry Andric return Error(ErrorLoc, "src and dst operand must be same"); 815349cc55cSDimitry Andric } 816349cc55cSDimitry Andric case Match_InvalidRegList: { 817349cc55cSDimitry Andric SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); 818349cc55cSDimitry Andric return Error(ErrorLoc, "invalid register list"); 819349cc55cSDimitry Andric } 820349cc55cSDimitry Andric } 821349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Result = " << Result); 822349cc55cSDimitry Andric llvm_unreachable("Unknown match type detected!"); 823fe6060f1SDimitry Andric } 824fe6060f1SDimitry Andric 82581ad6265SDimitry Andric bool CSKYAsmParser::processLRW(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) { 82681ad6265SDimitry Andric Inst.setLoc(IDLoc); 82781ad6265SDimitry Andric 82881ad6265SDimitry Andric unsigned Opcode; 82981ad6265SDimitry Andric MCOperand Op; 83081ad6265SDimitry Andric if (Inst.getOpcode() == CSKY::PseudoLRW16) 83181ad6265SDimitry Andric Opcode = CSKY::LRW16; 83281ad6265SDimitry Andric else 83381ad6265SDimitry Andric Opcode = CSKY::LRW32; 83481ad6265SDimitry Andric 83581ad6265SDimitry Andric if (Inst.getOperand(1).isImm()) { 83681ad6265SDimitry Andric if (isUInt<8>(Inst.getOperand(1).getImm()) && 83781ad6265SDimitry Andric Inst.getOperand(0).getReg() <= CSKY::R7) { 83881ad6265SDimitry Andric Opcode = CSKY::MOVI16; 83906c3fb27SDimitry Andric } else if (getSTI().hasFeature(CSKY::HasE2) && 84081ad6265SDimitry Andric isUInt<16>(Inst.getOperand(1).getImm())) { 84181ad6265SDimitry Andric Opcode = CSKY::MOVI32; 84281ad6265SDimitry Andric } else { 84381ad6265SDimitry Andric auto *Expr = getTargetStreamer().addConstantPoolEntry( 84481ad6265SDimitry Andric MCConstantExpr::create(Inst.getOperand(1).getImm(), getContext()), 84581ad6265SDimitry Andric Inst.getLoc()); 84681ad6265SDimitry Andric Inst.erase(std::prev(Inst.end())); 84781ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 84881ad6265SDimitry Andric } 84981ad6265SDimitry Andric } else { 85081ad6265SDimitry Andric const MCExpr *AdjustExpr = nullptr; 85181ad6265SDimitry Andric if (const CSKYMCExpr *CSKYExpr = 85281ad6265SDimitry Andric dyn_cast<CSKYMCExpr>(Inst.getOperand(1).getExpr())) { 85381ad6265SDimitry Andric if (CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSGD || 85481ad6265SDimitry Andric CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSIE || 85581ad6265SDimitry Andric CSKYExpr->getKind() == CSKYMCExpr::VK_CSKY_TLSLDM) { 85681ad6265SDimitry Andric MCSymbol *Dot = getContext().createNamedTempSymbol(); 85781ad6265SDimitry Andric Out.emitLabel(Dot); 85881ad6265SDimitry Andric AdjustExpr = MCSymbolRefExpr::create(Dot, getContext()); 85981ad6265SDimitry Andric } 86081ad6265SDimitry Andric } 86181ad6265SDimitry Andric auto *Expr = getTargetStreamer().addConstantPoolEntry( 86281ad6265SDimitry Andric Inst.getOperand(1).getExpr(), Inst.getLoc(), AdjustExpr); 86381ad6265SDimitry Andric Inst.erase(std::prev(Inst.end())); 86481ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 86581ad6265SDimitry Andric } 86681ad6265SDimitry Andric 86781ad6265SDimitry Andric Inst.setOpcode(Opcode); 86881ad6265SDimitry Andric 86981ad6265SDimitry Andric Out.emitInstruction(Inst, getSTI()); 87081ad6265SDimitry Andric return false; 87181ad6265SDimitry Andric } 87281ad6265SDimitry Andric 87381ad6265SDimitry Andric bool CSKYAsmParser::processJSRI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) { 87481ad6265SDimitry Andric Inst.setLoc(IDLoc); 87581ad6265SDimitry Andric 87681ad6265SDimitry Andric if (Inst.getOperand(0).isImm()) { 87781ad6265SDimitry Andric const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( 87881ad6265SDimitry Andric MCConstantExpr::create(Inst.getOperand(0).getImm(), getContext()), 87981ad6265SDimitry Andric Inst.getLoc()); 88081ad6265SDimitry Andric Inst.setOpcode(CSKY::JSRI32); 88181ad6265SDimitry Andric Inst.erase(std::prev(Inst.end())); 88281ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 88381ad6265SDimitry Andric } else { 88481ad6265SDimitry Andric const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( 88581ad6265SDimitry Andric Inst.getOperand(0).getExpr(), Inst.getLoc()); 88681ad6265SDimitry Andric Inst.setOpcode(CSKY::JBSR32); 88781ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 88881ad6265SDimitry Andric } 88981ad6265SDimitry Andric 89081ad6265SDimitry Andric Out.emitInstruction(Inst, getSTI()); 89181ad6265SDimitry Andric return false; 89281ad6265SDimitry Andric } 89381ad6265SDimitry Andric 89481ad6265SDimitry Andric bool CSKYAsmParser::processJMPI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) { 89581ad6265SDimitry Andric Inst.setLoc(IDLoc); 89681ad6265SDimitry Andric 89781ad6265SDimitry Andric if (Inst.getOperand(0).isImm()) { 89881ad6265SDimitry Andric const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( 89981ad6265SDimitry Andric MCConstantExpr::create(Inst.getOperand(0).getImm(), getContext()), 90081ad6265SDimitry Andric Inst.getLoc()); 90181ad6265SDimitry Andric Inst.setOpcode(CSKY::JMPI32); 90281ad6265SDimitry Andric Inst.erase(std::prev(Inst.end())); 90381ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 90481ad6265SDimitry Andric } else { 90581ad6265SDimitry Andric const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( 90681ad6265SDimitry Andric Inst.getOperand(0).getExpr(), Inst.getLoc()); 90781ad6265SDimitry Andric Inst.setOpcode(CSKY::JBR32); 90881ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 90981ad6265SDimitry Andric } 91081ad6265SDimitry Andric 91181ad6265SDimitry Andric Out.emitInstruction(Inst, getSTI()); 91281ad6265SDimitry Andric return false; 91381ad6265SDimitry Andric } 91481ad6265SDimitry Andric 915349cc55cSDimitry Andric bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 916349cc55cSDimitry Andric OperandVector &Operands, 917349cc55cSDimitry Andric MCStreamer &Out) { 918349cc55cSDimitry Andric 9190eae32dcSDimitry Andric switch (Inst.getOpcode()) { 9200eae32dcSDimitry Andric default: 9210eae32dcSDimitry Andric break; 9220eae32dcSDimitry Andric case CSKY::LDQ32: 9230eae32dcSDimitry Andric case CSKY::STQ32: 924349cc55cSDimitry Andric if (Inst.getOperand(1).getReg() != CSKY::R4 || 925349cc55cSDimitry Andric Inst.getOperand(2).getReg() != CSKY::R7) { 926349cc55cSDimitry Andric return Error(IDLoc, "Register sequence is not valid. 'r4-r7' expected"); 927349cc55cSDimitry Andric } 928349cc55cSDimitry Andric Inst.setOpcode(Inst.getOpcode() == CSKY::LDQ32 ? CSKY::LDM32 : CSKY::STM32); 9290eae32dcSDimitry Andric break; 9300eae32dcSDimitry Andric case CSKY::SEXT32: 9310eae32dcSDimitry Andric case CSKY::ZEXT32: 932349cc55cSDimitry Andric if (Inst.getOperand(2).getImm() < Inst.getOperand(3).getImm()) 933349cc55cSDimitry Andric return Error(IDLoc, "msb must be greater or equal to lsb"); 9340eae32dcSDimitry Andric break; 9350eae32dcSDimitry Andric case CSKY::INS32: 936349cc55cSDimitry Andric if (Inst.getOperand(3).getImm() < Inst.getOperand(4).getImm()) 937349cc55cSDimitry Andric return Error(IDLoc, "msb must be greater or equal to lsb"); 9380eae32dcSDimitry Andric break; 9390eae32dcSDimitry Andric case CSKY::IDLY32: 940349cc55cSDimitry Andric if (Inst.getOperand(0).getImm() > 32 || Inst.getOperand(0).getImm() < 0) 941349cc55cSDimitry Andric return Error(IDLoc, "n must be in range [0,32]"); 9420eae32dcSDimitry Andric break; 9430eae32dcSDimitry Andric case CSKY::ADDC32: 9440eae32dcSDimitry Andric case CSKY::SUBC32: 9450eae32dcSDimitry Andric case CSKY::ADDC16: 9460eae32dcSDimitry Andric case CSKY::SUBC16: 9470eae32dcSDimitry Andric Inst.erase(std::next(Inst.begin())); 9480eae32dcSDimitry Andric Inst.erase(std::prev(Inst.end())); 9490eae32dcSDimitry Andric Inst.insert(std::next(Inst.begin()), MCOperand::createReg(CSKY::C)); 9500eae32dcSDimitry Andric Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C)); 9510eae32dcSDimitry Andric break; 9520eae32dcSDimitry Andric case CSKY::CMPNEI32: 9530eae32dcSDimitry Andric case CSKY::CMPNEI16: 9540eae32dcSDimitry Andric case CSKY::CMPNE32: 9550eae32dcSDimitry Andric case CSKY::CMPNE16: 9560eae32dcSDimitry Andric case CSKY::CMPHSI32: 9570eae32dcSDimitry Andric case CSKY::CMPHSI16: 9580eae32dcSDimitry Andric case CSKY::CMPHS32: 9590eae32dcSDimitry Andric case CSKY::CMPHS16: 9600eae32dcSDimitry Andric case CSKY::CMPLTI32: 9610eae32dcSDimitry Andric case CSKY::CMPLTI16: 9620eae32dcSDimitry Andric case CSKY::CMPLT32: 9630eae32dcSDimitry Andric case CSKY::CMPLT16: 9640eae32dcSDimitry Andric case CSKY::BTSTI32: 9650eae32dcSDimitry Andric Inst.erase(Inst.begin()); 9660eae32dcSDimitry Andric Inst.insert(Inst.begin(), MCOperand::createReg(CSKY::C)); 9670eae32dcSDimitry Andric break; 9680eae32dcSDimitry Andric case CSKY::MVCV32: 9690eae32dcSDimitry Andric Inst.erase(std::next(Inst.begin())); 9700eae32dcSDimitry Andric Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C)); 9710eae32dcSDimitry Andric break; 97281ad6265SDimitry Andric case CSKY::PseudoLRW16: 97381ad6265SDimitry Andric case CSKY::PseudoLRW32: 97481ad6265SDimitry Andric return processLRW(Inst, IDLoc, Out); 97581ad6265SDimitry Andric case CSKY::PseudoJSRI32: 97681ad6265SDimitry Andric return processJSRI(Inst, IDLoc, Out); 97781ad6265SDimitry Andric case CSKY::PseudoJMPI32: 97881ad6265SDimitry Andric return processJMPI(Inst, IDLoc, Out); 97981ad6265SDimitry Andric case CSKY::JBSR32: 98081ad6265SDimitry Andric case CSKY::JBR16: 98181ad6265SDimitry Andric case CSKY::JBT16: 98281ad6265SDimitry Andric case CSKY::JBF16: 98381ad6265SDimitry Andric case CSKY::JBR32: 98481ad6265SDimitry Andric case CSKY::JBT32: 98581ad6265SDimitry Andric case CSKY::JBF32: 98681ad6265SDimitry Andric unsigned Num = Inst.getNumOperands() - 1; 98781ad6265SDimitry Andric assert(Inst.getOperand(Num).isExpr()); 98881ad6265SDimitry Andric 98981ad6265SDimitry Andric const MCExpr *Expr = getTargetStreamer().addConstantPoolEntry( 99081ad6265SDimitry Andric Inst.getOperand(Num).getExpr(), Inst.getLoc()); 99181ad6265SDimitry Andric 99281ad6265SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 99381ad6265SDimitry Andric break; 994349cc55cSDimitry Andric } 995349cc55cSDimitry Andric 9960eae32dcSDimitry Andric emitToStreamer(Out, Inst); 997349cc55cSDimitry Andric return false; 998fe6060f1SDimitry Andric } 999fe6060f1SDimitry Andric 1000fe6060f1SDimitry Andric // Attempts to match Name as a register (either using the default name or 1001fe6060f1SDimitry Andric // alternative ABI names), setting RegNo to the matching register. Upon 1002fe6060f1SDimitry Andric // failure, returns true and sets RegNo to 0. 10035f757f3fSDimitry Andric static bool matchRegisterNameHelper(const MCSubtargetInfo &STI, MCRegister &Reg, 10045f757f3fSDimitry Andric StringRef Name) { 10055f757f3fSDimitry Andric Reg = MatchRegisterName(Name); 1006fe6060f1SDimitry Andric 10075f757f3fSDimitry Andric if (Reg == CSKY::NoRegister) 10085f757f3fSDimitry Andric Reg = MatchRegisterAltName(Name); 1009fe6060f1SDimitry Andric 10105f757f3fSDimitry Andric return Reg == CSKY::NoRegister; 1011fe6060f1SDimitry Andric } 1012fe6060f1SDimitry Andric 10135f757f3fSDimitry Andric bool CSKYAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, 1014fe6060f1SDimitry Andric SMLoc &EndLoc) { 1015fe6060f1SDimitry Andric const AsmToken &Tok = getParser().getTok(); 1016fe6060f1SDimitry Andric StartLoc = Tok.getLoc(); 1017fe6060f1SDimitry Andric EndLoc = Tok.getEndLoc(); 1018fe6060f1SDimitry Andric StringRef Name = getLexer().getTok().getIdentifier(); 1019fe6060f1SDimitry Andric 10205f757f3fSDimitry Andric if (!matchRegisterNameHelper(getSTI(), Reg, Name)) { 1021fe6060f1SDimitry Andric getParser().Lex(); // Eat identifier token. 1022fe6060f1SDimitry Andric return false; 1023fe6060f1SDimitry Andric } 1024fe6060f1SDimitry Andric 102506c3fb27SDimitry Andric return true; 1026fe6060f1SDimitry Andric } 1027fe6060f1SDimitry Andric 102806c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parseRegister(OperandVector &Operands) { 1029fe6060f1SDimitry Andric SMLoc S = getLoc(); 1030fe6060f1SDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1031fe6060f1SDimitry Andric 1032fe6060f1SDimitry Andric switch (getLexer().getKind()) { 1033fe6060f1SDimitry Andric default: 103406c3fb27SDimitry Andric return ParseStatus::NoMatch; 1035fe6060f1SDimitry Andric case AsmToken::Identifier: { 1036fe6060f1SDimitry Andric StringRef Name = getLexer().getTok().getIdentifier(); 10375f757f3fSDimitry Andric MCRegister Reg; 1038fe6060f1SDimitry Andric 10395f757f3fSDimitry Andric if (matchRegisterNameHelper(getSTI(), Reg, Name)) 104006c3fb27SDimitry Andric return ParseStatus::NoMatch; 1041fe6060f1SDimitry Andric 1042fe6060f1SDimitry Andric getLexer().Lex(); 10435f757f3fSDimitry Andric Operands.push_back(CSKYOperand::createReg(Reg, S, E)); 1044fe6060f1SDimitry Andric 104506c3fb27SDimitry Andric return ParseStatus::Success; 1046fe6060f1SDimitry Andric } 1047fe6060f1SDimitry Andric } 1048fe6060f1SDimitry Andric } 1049fe6060f1SDimitry Andric 105006c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) { 1051fe6060f1SDimitry Andric assert(getLexer().is(AsmToken::LParen)); 1052fe6060f1SDimitry Andric 1053fe6060f1SDimitry Andric Operands.push_back(CSKYOperand::createToken("(", getLoc())); 1054fe6060f1SDimitry Andric 1055fe6060f1SDimitry Andric auto Tok = getParser().Lex(); // Eat '(' 1056fe6060f1SDimitry Andric 105706c3fb27SDimitry Andric if (!parseRegister(Operands).isSuccess()) { 1058fe6060f1SDimitry Andric getLexer().UnLex(Tok); 1059fe6060f1SDimitry Andric Operands.pop_back(); 106006c3fb27SDimitry Andric return ParseStatus::NoMatch; 1061349cc55cSDimitry Andric } 1062349cc55cSDimitry Andric 1063349cc55cSDimitry Andric if (getLexer().is(AsmToken::RParen)) { 1064349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createToken(")", getLoc())); 1065349cc55cSDimitry Andric getParser().Lex(); // Eat ')' 106606c3fb27SDimitry Andric return ParseStatus::Success; 1067fe6060f1SDimitry Andric } 1068fe6060f1SDimitry Andric 106906c3fb27SDimitry Andric if (getLexer().isNot(AsmToken::Comma)) 107006c3fb27SDimitry Andric return Error(getLoc(), "expected ','"); 1071fe6060f1SDimitry Andric 1072fe6060f1SDimitry Andric getParser().Lex(); // Eat ',' 1073fe6060f1SDimitry Andric 107406c3fb27SDimitry Andric if (parseRegister(Operands).isSuccess()) { 107506c3fb27SDimitry Andric if (getLexer().isNot(AsmToken::LessLess)) 107606c3fb27SDimitry Andric return Error(getLoc(), "expected '<<'"); 1077fe6060f1SDimitry Andric 1078fe6060f1SDimitry Andric Operands.push_back(CSKYOperand::createToken("<<", getLoc())); 1079fe6060f1SDimitry Andric 1080fe6060f1SDimitry Andric getParser().Lex(); // Eat '<<' 1081fe6060f1SDimitry Andric 108206c3fb27SDimitry Andric if (!parseImmediate(Operands).isSuccess()) 108306c3fb27SDimitry Andric return Error(getLoc(), "expected imm"); 108406c3fb27SDimitry Andric 108506c3fb27SDimitry Andric } else if (!parseImmediate(Operands).isSuccess()) { 108606c3fb27SDimitry Andric return Error(getLoc(), "expected imm"); 1087fe6060f1SDimitry Andric } 1088fe6060f1SDimitry Andric 108906c3fb27SDimitry Andric if (getLexer().isNot(AsmToken::RParen)) 109006c3fb27SDimitry Andric return Error(getLoc(), "expected ')'"); 1091fe6060f1SDimitry Andric 1092fe6060f1SDimitry Andric Operands.push_back(CSKYOperand::createToken(")", getLoc())); 1093fe6060f1SDimitry Andric 1094fe6060f1SDimitry Andric getParser().Lex(); // Eat ')' 1095fe6060f1SDimitry Andric 109606c3fb27SDimitry Andric return ParseStatus::Success; 1097fe6060f1SDimitry Andric } 1098fe6060f1SDimitry Andric 109906c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parseImmediate(OperandVector &Operands) { 1100fe6060f1SDimitry Andric switch (getLexer().getKind()) { 1101fe6060f1SDimitry Andric default: 110206c3fb27SDimitry Andric return ParseStatus::NoMatch; 1103fe6060f1SDimitry Andric case AsmToken::LParen: 1104fe6060f1SDimitry Andric case AsmToken::Minus: 1105fe6060f1SDimitry Andric case AsmToken::Plus: 1106fe6060f1SDimitry Andric case AsmToken::Integer: 1107fe6060f1SDimitry Andric case AsmToken::String: 1108fe6060f1SDimitry Andric break; 1109fe6060f1SDimitry Andric } 1110fe6060f1SDimitry Andric 1111fe6060f1SDimitry Andric const MCExpr *IdVal; 1112fe6060f1SDimitry Andric SMLoc S = getLoc(); 111306c3fb27SDimitry Andric if (getParser().parseExpression(IdVal)) 111406c3fb27SDimitry Andric return Error(getLoc(), "unknown expression"); 1115fe6060f1SDimitry Andric 1116fe6060f1SDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1117fe6060f1SDimitry Andric Operands.push_back(CSKYOperand::createImm(IdVal, S, E)); 111806c3fb27SDimitry Andric return ParseStatus::Success; 1119fe6060f1SDimitry Andric } 1120fe6060f1SDimitry Andric 1121fe6060f1SDimitry Andric /// Looks at a token type and creates the relevant operand from this 1122fe6060f1SDimitry Andric /// information, adding to Operands. If operand was parsed, returns false, else 1123fe6060f1SDimitry Andric /// true. 1124fe6060f1SDimitry Andric bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 1125fe6060f1SDimitry Andric // Check if the current operand has a custom associated parser, if so, try to 1126fe6060f1SDimitry Andric // custom parse the operand, or fallback to the general approach. 112706c3fb27SDimitry Andric ParseStatus Result = 1128fe6060f1SDimitry Andric MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true); 112906c3fb27SDimitry Andric if (Result.isSuccess()) 1130fe6060f1SDimitry Andric return false; 113106c3fb27SDimitry Andric if (Result.isFailure()) 1132fe6060f1SDimitry Andric return true; 1133fe6060f1SDimitry Andric 1134fe6060f1SDimitry Andric // Attempt to parse token as register 1135349cc55cSDimitry Andric auto Res = parseRegister(Operands); 113606c3fb27SDimitry Andric if (Res.isSuccess()) 1137fe6060f1SDimitry Andric return false; 113806c3fb27SDimitry Andric if (Res.isFailure()) 1139349cc55cSDimitry Andric return true; 1140fe6060f1SDimitry Andric 1141fe6060f1SDimitry Andric // Attempt to parse token as (register, imm) 1142349cc55cSDimitry Andric if (getLexer().is(AsmToken::LParen)) { 1143349cc55cSDimitry Andric Res = parseBaseRegImm(Operands); 114406c3fb27SDimitry Andric if (Res.isSuccess()) 1145fe6060f1SDimitry Andric return false; 114606c3fb27SDimitry Andric if (Res.isFailure()) 1147349cc55cSDimitry Andric return true; 1148349cc55cSDimitry Andric } 1149fe6060f1SDimitry Andric 1150349cc55cSDimitry Andric Res = parseImmediate(Operands); 115106c3fb27SDimitry Andric if (Res.isSuccess()) 1152fe6060f1SDimitry Andric return false; 115306c3fb27SDimitry Andric if (Res.isFailure()) 1154349cc55cSDimitry Andric return true; 1155fe6060f1SDimitry Andric 1156fe6060f1SDimitry Andric // Finally we have exhausted all options and must declare defeat. 1157fe6060f1SDimitry Andric Error(getLoc(), "unknown operand"); 1158fe6060f1SDimitry Andric return true; 1159fe6060f1SDimitry Andric } 1160fe6060f1SDimitry Andric 116106c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) { 1162fe6060f1SDimitry Andric SMLoc S = getLoc(); 1163fe6060f1SDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1164349cc55cSDimitry Andric const MCExpr *Res; 1165fe6060f1SDimitry Andric 1166fe6060f1SDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) 116706c3fb27SDimitry Andric return ParseStatus::NoMatch; 1168fe6060f1SDimitry Andric 1169fe6060f1SDimitry Andric StringRef Identifier; 1170349cc55cSDimitry Andric AsmToken Tok = getLexer().getTok(); 1171349cc55cSDimitry Andric 117206c3fb27SDimitry Andric if (getParser().parseIdentifier(Identifier)) 117306c3fb27SDimitry Andric return Error(getLoc(), "unknown identifier"); 1174fe6060f1SDimitry Andric 1175fe6060f1SDimitry Andric CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None; 1176fe6060f1SDimitry Andric if (Identifier.consume_back("@GOT")) 1177fe6060f1SDimitry Andric Kind = CSKYMCExpr::VK_CSKY_GOT; 1178fe6060f1SDimitry Andric else if (Identifier.consume_back("@GOTOFF")) 1179fe6060f1SDimitry Andric Kind = CSKYMCExpr::VK_CSKY_GOTOFF; 1180fe6060f1SDimitry Andric else if (Identifier.consume_back("@PLT")) 1181fe6060f1SDimitry Andric Kind = CSKYMCExpr::VK_CSKY_PLT; 1182fe6060f1SDimitry Andric else if (Identifier.consume_back("@GOTPC")) 1183fe6060f1SDimitry Andric Kind = CSKYMCExpr::VK_CSKY_GOTPC; 1184349cc55cSDimitry Andric else if (Identifier.consume_back("@TLSGD32")) 1185349cc55cSDimitry Andric Kind = CSKYMCExpr::VK_CSKY_TLSGD; 1186349cc55cSDimitry Andric else if (Identifier.consume_back("@GOTTPOFF")) 1187349cc55cSDimitry Andric Kind = CSKYMCExpr::VK_CSKY_TLSIE; 1188349cc55cSDimitry Andric else if (Identifier.consume_back("@TPOFF")) 1189349cc55cSDimitry Andric Kind = CSKYMCExpr::VK_CSKY_TLSLE; 1190349cc55cSDimitry Andric else if (Identifier.consume_back("@TLSLDM32")) 1191349cc55cSDimitry Andric Kind = CSKYMCExpr::VK_CSKY_TLSLDM; 1192349cc55cSDimitry Andric else if (Identifier.consume_back("@TLSLDO32")) 1193349cc55cSDimitry Andric Kind = CSKYMCExpr::VK_CSKY_TLSLDO; 1194fe6060f1SDimitry Andric 1195349cc55cSDimitry Andric MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier); 1196fe6060f1SDimitry Andric 1197349cc55cSDimitry Andric if (!Sym) 1198349cc55cSDimitry Andric Sym = getContext().getOrCreateSymbol(Identifier); 1199349cc55cSDimitry Andric 1200349cc55cSDimitry Andric if (Sym->isVariable()) { 1201349cc55cSDimitry Andric const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false); 1202349cc55cSDimitry Andric if (!isa<MCSymbolRefExpr>(V)) { 1203349cc55cSDimitry Andric getLexer().UnLex(Tok); // Put back if it's not a bare symbol. 120406c3fb27SDimitry Andric return Error(getLoc(), "unknown symbol"); 1205349cc55cSDimitry Andric } 1206349cc55cSDimitry Andric Res = V; 1207349cc55cSDimitry Andric } else 1208349cc55cSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 1209349cc55cSDimitry Andric 1210349cc55cSDimitry Andric MCBinaryExpr::Opcode Opcode; 1211349cc55cSDimitry Andric switch (getLexer().getKind()) { 1212349cc55cSDimitry Andric default: 1213fe6060f1SDimitry Andric if (Kind != CSKYMCExpr::VK_CSKY_None) 1214fe6060f1SDimitry Andric Res = CSKYMCExpr::create(Res, Kind, getContext()); 1215fe6060f1SDimitry Andric 1216fe6060f1SDimitry Andric Operands.push_back(CSKYOperand::createImm(Res, S, E)); 121706c3fb27SDimitry Andric return ParseStatus::Success; 1218349cc55cSDimitry Andric case AsmToken::Plus: 1219349cc55cSDimitry Andric Opcode = MCBinaryExpr::Add; 1220349cc55cSDimitry Andric break; 1221349cc55cSDimitry Andric case AsmToken::Minus: 1222349cc55cSDimitry Andric Opcode = MCBinaryExpr::Sub; 1223349cc55cSDimitry Andric break; 1224349cc55cSDimitry Andric } 1225349cc55cSDimitry Andric 1226349cc55cSDimitry Andric getLexer().Lex(); // eat + or - 1227349cc55cSDimitry Andric 1228349cc55cSDimitry Andric const MCExpr *Expr; 122906c3fb27SDimitry Andric if (getParser().parseExpression(Expr)) 123006c3fb27SDimitry Andric return Error(getLoc(), "unknown expression"); 1231349cc55cSDimitry Andric Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext()); 1232349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createImm(Res, S, E)); 123306c3fb27SDimitry Andric return ParseStatus::Success; 1234349cc55cSDimitry Andric } 1235349cc55cSDimitry Andric 123606c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parseDataSymbol(OperandVector &Operands) { 1237349cc55cSDimitry Andric SMLoc S = getLoc(); 1238349cc55cSDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1239349cc55cSDimitry Andric const MCExpr *Res; 1240349cc55cSDimitry Andric 124106c3fb27SDimitry Andric if (!parseOptionalToken(AsmToken::LBrac)) 124206c3fb27SDimitry Andric return ParseStatus::NoMatch; 1243349cc55cSDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) { 1244349cc55cSDimitry Andric const MCExpr *Expr; 124506c3fb27SDimitry Andric if (getParser().parseExpression(Expr)) 124606c3fb27SDimitry Andric return Error(getLoc(), "unknown expression"); 1247349cc55cSDimitry Andric 124806c3fb27SDimitry Andric if (parseToken(AsmToken::RBrac, "expected ']'")) 124906c3fb27SDimitry Andric return ParseStatus::Failure; 1250349cc55cSDimitry Andric 1251349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E)); 125206c3fb27SDimitry Andric return ParseStatus::Success; 1253349cc55cSDimitry Andric } 1254349cc55cSDimitry Andric 1255349cc55cSDimitry Andric AsmToken Tok = getLexer().getTok(); 1256349cc55cSDimitry Andric StringRef Identifier; 1257349cc55cSDimitry Andric 125806c3fb27SDimitry Andric if (getParser().parseIdentifier(Identifier)) 125906c3fb27SDimitry Andric return Error(getLoc(), "unknown identifier " + Identifier); 1260349cc55cSDimitry Andric 1261349cc55cSDimitry Andric CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None; 1262349cc55cSDimitry Andric if (Identifier.consume_back("@GOT")) 1263349cc55cSDimitry Andric Kind = CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4; 1264349cc55cSDimitry Andric else if (Identifier.consume_back("@PLT")) 1265349cc55cSDimitry Andric Kind = CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4; 1266349cc55cSDimitry Andric 1267349cc55cSDimitry Andric MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier); 1268349cc55cSDimitry Andric 1269349cc55cSDimitry Andric if (!Sym) 1270349cc55cSDimitry Andric Sym = getContext().getOrCreateSymbol(Identifier); 1271349cc55cSDimitry Andric 1272349cc55cSDimitry Andric if (Sym->isVariable()) { 1273349cc55cSDimitry Andric const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false); 1274349cc55cSDimitry Andric if (!isa<MCSymbolRefExpr>(V)) { 1275349cc55cSDimitry Andric getLexer().UnLex(Tok); // Put back if it's not a bare symbol. 127606c3fb27SDimitry Andric return Error(getLoc(), "unknown symbol"); 1277349cc55cSDimitry Andric } 1278349cc55cSDimitry Andric Res = V; 1279349cc55cSDimitry Andric } else { 1280349cc55cSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 1281349cc55cSDimitry Andric } 1282349cc55cSDimitry Andric 1283349cc55cSDimitry Andric MCBinaryExpr::Opcode Opcode; 1284349cc55cSDimitry Andric switch (getLexer().getKind()) { 1285349cc55cSDimitry Andric default: 128606c3fb27SDimitry Andric return Error(getLoc(), "unknown symbol"); 1287349cc55cSDimitry Andric case AsmToken::RBrac: 1288349cc55cSDimitry Andric 1289349cc55cSDimitry Andric getLexer().Lex(); // Eat ']'. 1290349cc55cSDimitry Andric 1291349cc55cSDimitry Andric if (Kind != CSKYMCExpr::VK_CSKY_None) 1292349cc55cSDimitry Andric Res = CSKYMCExpr::create(Res, Kind, getContext()); 1293349cc55cSDimitry Andric 1294349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E)); 129506c3fb27SDimitry Andric return ParseStatus::Success; 1296349cc55cSDimitry Andric case AsmToken::Plus: 1297349cc55cSDimitry Andric Opcode = MCBinaryExpr::Add; 1298349cc55cSDimitry Andric break; 1299349cc55cSDimitry Andric case AsmToken::Minus: 1300349cc55cSDimitry Andric Opcode = MCBinaryExpr::Sub; 1301349cc55cSDimitry Andric break; 1302349cc55cSDimitry Andric } 1303349cc55cSDimitry Andric 1304349cc55cSDimitry Andric getLexer().Lex(); // eat + or - 1305349cc55cSDimitry Andric 1306349cc55cSDimitry Andric const MCExpr *Expr; 130706c3fb27SDimitry Andric if (getParser().parseExpression(Expr)) 130806c3fb27SDimitry Andric return Error(getLoc(), "unknown expression"); 130906c3fb27SDimitry Andric if (parseToken(AsmToken::RBrac, "expected ']'")) 131006c3fb27SDimitry Andric return ParseStatus::Failure; 1311349cc55cSDimitry Andric 1312349cc55cSDimitry Andric Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext()); 1313349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E)); 131406c3fb27SDimitry Andric return ParseStatus::Success; 1315fe6060f1SDimitry Andric } 1316fe6060f1SDimitry Andric 131706c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) { 1318fe6060f1SDimitry Andric SMLoc S = getLoc(); 1319fe6060f1SDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1320349cc55cSDimitry Andric const MCExpr *Res; 1321fe6060f1SDimitry Andric 132206c3fb27SDimitry Andric if (!parseOptionalToken(AsmToken::LBrac)) 132306c3fb27SDimitry Andric return ParseStatus::NoMatch; 1324fe6060f1SDimitry Andric 1325349cc55cSDimitry Andric if (getLexer().getKind() != AsmToken::Identifier) { 1326349cc55cSDimitry Andric const MCExpr *Expr; 132706c3fb27SDimitry Andric if (getParser().parseExpression(Expr)) 132806c3fb27SDimitry Andric return Error(getLoc(), "unknown expression"); 132906c3fb27SDimitry Andric if (parseToken(AsmToken::RBrac)) 133006c3fb27SDimitry Andric return ParseStatus::Failure; 1331fe6060f1SDimitry Andric 1332349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createConstpoolOp(Expr, S, E)); 133306c3fb27SDimitry Andric return ParseStatus::Success; 1334349cc55cSDimitry Andric } 1335349cc55cSDimitry Andric 1336349cc55cSDimitry Andric AsmToken Tok = getLexer().getTok(); 1337349cc55cSDimitry Andric StringRef Identifier; 1338349cc55cSDimitry Andric 133906c3fb27SDimitry Andric if (getParser().parseIdentifier(Identifier)) 134006c3fb27SDimitry Andric return Error(getLoc(), "unknown identifier"); 1341349cc55cSDimitry Andric 1342349cc55cSDimitry Andric MCSymbol *Sym = getContext().getInlineAsmLabel(Identifier); 1343349cc55cSDimitry Andric 1344349cc55cSDimitry Andric if (!Sym) 1345349cc55cSDimitry Andric Sym = getContext().getOrCreateSymbol(Identifier); 1346349cc55cSDimitry Andric 1347349cc55cSDimitry Andric if (Sym->isVariable()) { 1348349cc55cSDimitry Andric const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false); 1349349cc55cSDimitry Andric if (!isa<MCSymbolRefExpr>(V)) { 1350349cc55cSDimitry Andric getLexer().UnLex(Tok); // Put back if it's not a bare symbol. 135106c3fb27SDimitry Andric return Error(getLoc(), "unknown symbol"); 1352349cc55cSDimitry Andric } 1353349cc55cSDimitry Andric Res = V; 1354349cc55cSDimitry Andric } else { 1355349cc55cSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 1356349cc55cSDimitry Andric } 1357349cc55cSDimitry Andric 1358349cc55cSDimitry Andric MCBinaryExpr::Opcode Opcode; 1359349cc55cSDimitry Andric switch (getLexer().getKind()) { 1360349cc55cSDimitry Andric default: 136106c3fb27SDimitry Andric return Error(getLoc(), "unknown symbol"); 1362349cc55cSDimitry Andric case AsmToken::RBrac: 1363349cc55cSDimitry Andric 1364349cc55cSDimitry Andric getLexer().Lex(); // Eat ']'. 1365349cc55cSDimitry Andric 1366349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E)); 136706c3fb27SDimitry Andric return ParseStatus::Success; 1368349cc55cSDimitry Andric case AsmToken::Plus: 1369349cc55cSDimitry Andric Opcode = MCBinaryExpr::Add; 1370349cc55cSDimitry Andric break; 1371349cc55cSDimitry Andric case AsmToken::Minus: 1372349cc55cSDimitry Andric Opcode = MCBinaryExpr::Sub; 1373349cc55cSDimitry Andric break; 1374349cc55cSDimitry Andric } 1375349cc55cSDimitry Andric 1376349cc55cSDimitry Andric getLexer().Lex(); // eat + or - 1377349cc55cSDimitry Andric 1378349cc55cSDimitry Andric const MCExpr *Expr; 137906c3fb27SDimitry Andric if (getParser().parseExpression(Expr)) 138006c3fb27SDimitry Andric return Error(getLoc(), "unknown expression"); 138106c3fb27SDimitry Andric if (parseToken(AsmToken::RBrac, "expected ']'")) 138206c3fb27SDimitry Andric return ParseStatus::Failure; 1383349cc55cSDimitry Andric 1384349cc55cSDimitry Andric Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext()); 1385349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createConstpoolOp(Res, S, E)); 138606c3fb27SDimitry Andric return ParseStatus::Success; 1387349cc55cSDimitry Andric } 1388349cc55cSDimitry Andric 138906c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parsePSRFlag(OperandVector &Operands) { 1390349cc55cSDimitry Andric SMLoc S = getLoc(); 1391349cc55cSDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1392349cc55cSDimitry Andric 1393349cc55cSDimitry Andric unsigned Flag = 0; 1394349cc55cSDimitry Andric 1395349cc55cSDimitry Andric while (getLexer().isNot(AsmToken::EndOfStatement)) { 1396349cc55cSDimitry Andric StringRef Identifier; 139706c3fb27SDimitry Andric if (getParser().parseIdentifier(Identifier)) 139806c3fb27SDimitry Andric return Error(getLoc(), "unknown identifier " + Identifier); 1399349cc55cSDimitry Andric 1400349cc55cSDimitry Andric if (Identifier == "sie") 1401349cc55cSDimitry Andric Flag = (1 << 4) | Flag; 1402349cc55cSDimitry Andric else if (Identifier == "ee") 1403349cc55cSDimitry Andric Flag = (1 << 3) | Flag; 1404349cc55cSDimitry Andric else if (Identifier == "ie") 1405349cc55cSDimitry Andric Flag = (1 << 2) | Flag; 1406349cc55cSDimitry Andric else if (Identifier == "fe") 1407349cc55cSDimitry Andric Flag = (1 << 1) | Flag; 1408349cc55cSDimitry Andric else if (Identifier == "af") 1409349cc55cSDimitry Andric Flag = (1 << 0) | Flag; 141006c3fb27SDimitry Andric else 141106c3fb27SDimitry Andric return Error(getLoc(), "expected " + Identifier); 1412349cc55cSDimitry Andric 1413349cc55cSDimitry Andric if (getLexer().is(AsmToken::EndOfStatement)) 1414349cc55cSDimitry Andric break; 1415349cc55cSDimitry Andric 141606c3fb27SDimitry Andric if (parseToken(AsmToken::Comma, "expected ','")) 141706c3fb27SDimitry Andric return ParseStatus::Failure; 1418349cc55cSDimitry Andric } 1419349cc55cSDimitry Andric 1420349cc55cSDimitry Andric Operands.push_back( 1421349cc55cSDimitry Andric CSKYOperand::createImm(MCConstantExpr::create(Flag, getContext()), S, E)); 142206c3fb27SDimitry Andric return ParseStatus::Success; 1423349cc55cSDimitry Andric } 1424349cc55cSDimitry Andric 142506c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parseRegSeq(OperandVector &Operands) { 1426349cc55cSDimitry Andric SMLoc S = getLoc(); 1427349cc55cSDimitry Andric 142806c3fb27SDimitry Andric if (!parseRegister(Operands).isSuccess()) 142906c3fb27SDimitry Andric return ParseStatus::NoMatch; 1430349cc55cSDimitry Andric 1431349cc55cSDimitry Andric auto Ry = Operands.back()->getReg(); 1432349cc55cSDimitry Andric Operands.pop_back(); 1433349cc55cSDimitry Andric 143406c3fb27SDimitry Andric if (parseToken(AsmToken::Minus, "expected '-'")) 143506c3fb27SDimitry Andric return ParseStatus::Failure; 143606c3fb27SDimitry Andric if (!parseRegister(Operands).isSuccess()) 143706c3fb27SDimitry Andric return Error(getLoc(), "invalid register"); 1438349cc55cSDimitry Andric 1439349cc55cSDimitry Andric auto Rz = Operands.back()->getReg(); 1440349cc55cSDimitry Andric Operands.pop_back(); 1441349cc55cSDimitry Andric 1442349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createRegSeq(Ry, Rz, S)); 144306c3fb27SDimitry Andric return ParseStatus::Success; 1444349cc55cSDimitry Andric } 1445349cc55cSDimitry Andric 144606c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parseRegList(OperandVector &Operands) { 1447349cc55cSDimitry Andric SMLoc S = getLoc(); 1448349cc55cSDimitry Andric 1449349cc55cSDimitry Andric SmallVector<unsigned, 4> reglist; 1450349cc55cSDimitry Andric 1451349cc55cSDimitry Andric while (true) { 1452349cc55cSDimitry Andric 145306c3fb27SDimitry Andric if (!parseRegister(Operands).isSuccess()) 145406c3fb27SDimitry Andric return Error(getLoc(), "invalid register"); 1455349cc55cSDimitry Andric 1456349cc55cSDimitry Andric auto Ry = Operands.back()->getReg(); 1457349cc55cSDimitry Andric Operands.pop_back(); 1458349cc55cSDimitry Andric 145906c3fb27SDimitry Andric if (parseOptionalToken(AsmToken::Minus)) { 146006c3fb27SDimitry Andric if (!parseRegister(Operands).isSuccess()) 146106c3fb27SDimitry Andric return Error(getLoc(), "invalid register"); 1462349cc55cSDimitry Andric 1463349cc55cSDimitry Andric auto Rz = Operands.back()->getReg(); 1464349cc55cSDimitry Andric Operands.pop_back(); 1465349cc55cSDimitry Andric 1466349cc55cSDimitry Andric reglist.push_back(Ry); 1467349cc55cSDimitry Andric reglist.push_back(Rz); 1468349cc55cSDimitry Andric 146906c3fb27SDimitry Andric if (getLexer().is(AsmToken::EndOfStatement)) 1470349cc55cSDimitry Andric break; 147106c3fb27SDimitry Andric (void)parseOptionalToken(AsmToken::Comma); 147206c3fb27SDimitry Andric } else if (parseOptionalToken(AsmToken::Comma)) { 1473349cc55cSDimitry Andric reglist.push_back(Ry); 1474349cc55cSDimitry Andric reglist.push_back(Ry); 1475349cc55cSDimitry Andric } else if (getLexer().is(AsmToken::EndOfStatement)) { 1476349cc55cSDimitry Andric reglist.push_back(Ry); 1477349cc55cSDimitry Andric reglist.push_back(Ry); 1478349cc55cSDimitry Andric break; 1479349cc55cSDimitry Andric } else { 148006c3fb27SDimitry Andric return Error(getLoc(), "invalid register list"); 1481349cc55cSDimitry Andric } 1482349cc55cSDimitry Andric } 1483349cc55cSDimitry Andric 1484349cc55cSDimitry Andric Operands.push_back(CSKYOperand::createRegList(reglist, S)); 148506c3fb27SDimitry Andric return ParseStatus::Success; 1486fe6060f1SDimitry Andric } 1487fe6060f1SDimitry Andric 1488fe6060f1SDimitry Andric bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 1489fe6060f1SDimitry Andric SMLoc NameLoc, OperandVector &Operands) { 1490fe6060f1SDimitry Andric // First operand is token for instruction. 1491fe6060f1SDimitry Andric Operands.push_back(CSKYOperand::createToken(Name, NameLoc)); 1492fe6060f1SDimitry Andric 1493fe6060f1SDimitry Andric // If there are no more operands, then finish. 1494fe6060f1SDimitry Andric if (getLexer().is(AsmToken::EndOfStatement)) 1495fe6060f1SDimitry Andric return false; 1496fe6060f1SDimitry Andric 1497fe6060f1SDimitry Andric // Parse first operand. 1498fe6060f1SDimitry Andric if (parseOperand(Operands, Name)) 1499fe6060f1SDimitry Andric return true; 1500fe6060f1SDimitry Andric 1501fe6060f1SDimitry Andric // Parse until end of statement, consuming commas between operands. 150206c3fb27SDimitry Andric while (parseOptionalToken(AsmToken::Comma)) 1503fe6060f1SDimitry Andric if (parseOperand(Operands, Name)) 1504fe6060f1SDimitry Andric return true; 1505fe6060f1SDimitry Andric 1506fe6060f1SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) { 1507fe6060f1SDimitry Andric SMLoc Loc = getLexer().getLoc(); 1508fe6060f1SDimitry Andric getParser().eatToEndOfStatement(); 1509fe6060f1SDimitry Andric return Error(Loc, "unexpected token"); 1510fe6060f1SDimitry Andric } 1511fe6060f1SDimitry Andric 1512fe6060f1SDimitry Andric getParser().Lex(); // Consume the EndOfStatement. 1513fe6060f1SDimitry Andric return false; 1514fe6060f1SDimitry Andric } 1515fe6060f1SDimitry Andric 15165f757f3fSDimitry Andric ParseStatus CSKYAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 1517fe6060f1SDimitry Andric SMLoc &EndLoc) { 1518fe6060f1SDimitry Andric const AsmToken &Tok = getParser().getTok(); 1519fe6060f1SDimitry Andric StartLoc = Tok.getLoc(); 1520fe6060f1SDimitry Andric EndLoc = Tok.getEndLoc(); 1521fe6060f1SDimitry Andric 1522fe6060f1SDimitry Andric StringRef Name = getLexer().getTok().getIdentifier(); 1523fe6060f1SDimitry Andric 15245f757f3fSDimitry Andric if (matchRegisterNameHelper(getSTI(), Reg, Name)) 15255f757f3fSDimitry Andric return ParseStatus::NoMatch; 1526fe6060f1SDimitry Andric 1527fe6060f1SDimitry Andric getParser().Lex(); // Eat identifier token. 15285f757f3fSDimitry Andric return ParseStatus::Success; 1529fe6060f1SDimitry Andric } 1530fe6060f1SDimitry Andric 153106c3fb27SDimitry Andric ParseStatus CSKYAsmParser::parseDirective(AsmToken DirectiveID) { 153281ad6265SDimitry Andric StringRef IDVal = DirectiveID.getString(); 153381ad6265SDimitry Andric 153481ad6265SDimitry Andric if (IDVal == ".csky_attribute") 153581ad6265SDimitry Andric return parseDirectiveAttribute(); 153681ad6265SDimitry Andric 153706c3fb27SDimitry Andric return ParseStatus::NoMatch; 153881ad6265SDimitry Andric } 153981ad6265SDimitry Andric 154081ad6265SDimitry Andric /// parseDirectiveAttribute 154181ad6265SDimitry Andric /// ::= .attribute expression ',' ( expression | "string" ) 154281ad6265SDimitry Andric bool CSKYAsmParser::parseDirectiveAttribute() { 154381ad6265SDimitry Andric MCAsmParser &Parser = getParser(); 154481ad6265SDimitry Andric int64_t Tag; 154581ad6265SDimitry Andric SMLoc TagLoc; 154681ad6265SDimitry Andric TagLoc = Parser.getTok().getLoc(); 154781ad6265SDimitry Andric if (Parser.getTok().is(AsmToken::Identifier)) { 154881ad6265SDimitry Andric StringRef Name = Parser.getTok().getIdentifier(); 1549bdd1243dSDimitry Andric std::optional<unsigned> Ret = 155081ad6265SDimitry Andric ELFAttrs::attrTypeFromString(Name, CSKYAttrs::getCSKYAttributeTags()); 155106c3fb27SDimitry Andric if (!Ret) 155206c3fb27SDimitry Andric return Error(TagLoc, "attribute name not recognised: " + Name); 1553bdd1243dSDimitry Andric Tag = *Ret; 155481ad6265SDimitry Andric Parser.Lex(); 155581ad6265SDimitry Andric } else { 155681ad6265SDimitry Andric const MCExpr *AttrExpr; 155781ad6265SDimitry Andric 155881ad6265SDimitry Andric TagLoc = Parser.getTok().getLoc(); 155981ad6265SDimitry Andric if (Parser.parseExpression(AttrExpr)) 156081ad6265SDimitry Andric return true; 156181ad6265SDimitry Andric 156281ad6265SDimitry Andric const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr); 156306c3fb27SDimitry Andric if (!CE) 156406c3fb27SDimitry Andric return Error(TagLoc, "expected numeric constant"); 156581ad6265SDimitry Andric 156681ad6265SDimitry Andric Tag = CE->getValue(); 156781ad6265SDimitry Andric } 156881ad6265SDimitry Andric 156906c3fb27SDimitry Andric if (Parser.parseComma()) 157081ad6265SDimitry Andric return true; 157181ad6265SDimitry Andric 157281ad6265SDimitry Andric StringRef StringValue; 157381ad6265SDimitry Andric int64_t IntegerValue = 0; 157481ad6265SDimitry Andric bool IsIntegerValue = ((Tag != CSKYAttrs::CSKY_ARCH_NAME) && 157581ad6265SDimitry Andric (Tag != CSKYAttrs::CSKY_CPU_NAME) && 157681ad6265SDimitry Andric (Tag != CSKYAttrs::CSKY_FPU_NUMBER_MODULE)); 157781ad6265SDimitry Andric 157881ad6265SDimitry Andric SMLoc ValueExprLoc = Parser.getTok().getLoc(); 157981ad6265SDimitry Andric if (IsIntegerValue) { 158081ad6265SDimitry Andric const MCExpr *ValueExpr; 158181ad6265SDimitry Andric if (Parser.parseExpression(ValueExpr)) 158281ad6265SDimitry Andric return true; 158381ad6265SDimitry Andric 158481ad6265SDimitry Andric const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr); 158581ad6265SDimitry Andric if (!CE) 158681ad6265SDimitry Andric return Error(ValueExprLoc, "expected numeric constant"); 158781ad6265SDimitry Andric IntegerValue = CE->getValue(); 158881ad6265SDimitry Andric } else { 158981ad6265SDimitry Andric if (Parser.getTok().isNot(AsmToken::String)) 159081ad6265SDimitry Andric return Error(Parser.getTok().getLoc(), "expected string constant"); 159181ad6265SDimitry Andric 159281ad6265SDimitry Andric StringValue = Parser.getTok().getStringContents(); 159381ad6265SDimitry Andric Parser.Lex(); 159481ad6265SDimitry Andric } 159581ad6265SDimitry Andric 159681ad6265SDimitry Andric if (Parser.parseEOL()) 159781ad6265SDimitry Andric return true; 159881ad6265SDimitry Andric 159981ad6265SDimitry Andric if (IsIntegerValue) 160081ad6265SDimitry Andric getTargetStreamer().emitAttribute(Tag, IntegerValue); 160181ad6265SDimitry Andric else if (Tag != CSKYAttrs::CSKY_ARCH_NAME && Tag != CSKYAttrs::CSKY_CPU_NAME) 160281ad6265SDimitry Andric getTargetStreamer().emitTextAttribute(Tag, StringValue); 160381ad6265SDimitry Andric else { 160481ad6265SDimitry Andric CSKY::ArchKind ID = (Tag == CSKYAttrs::CSKY_ARCH_NAME) 160581ad6265SDimitry Andric ? CSKY::parseArch(StringValue) 160681ad6265SDimitry Andric : CSKY::parseCPUArch(StringValue); 160781ad6265SDimitry Andric if (ID == CSKY::ArchKind::INVALID) 160881ad6265SDimitry Andric return Error(ValueExprLoc, (Tag == CSKYAttrs::CSKY_ARCH_NAME) 160981ad6265SDimitry Andric ? "unknown arch name" 161081ad6265SDimitry Andric : "unknown cpu name"); 161181ad6265SDimitry Andric 161281ad6265SDimitry Andric getTargetStreamer().emitTextAttribute(Tag, StringValue); 161381ad6265SDimitry Andric } 161481ad6265SDimitry Andric 161581ad6265SDimitry Andric return false; 161681ad6265SDimitry Andric } 161781ad6265SDimitry Andric 161881ad6265SDimitry Andric unsigned CSKYAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 161981ad6265SDimitry Andric unsigned Kind) { 162081ad6265SDimitry Andric CSKYOperand &Op = static_cast<CSKYOperand &>(AsmOp); 162181ad6265SDimitry Andric 162281ad6265SDimitry Andric if (!Op.isReg()) 162381ad6265SDimitry Andric return Match_InvalidOperand; 162481ad6265SDimitry Andric 162581ad6265SDimitry Andric MCRegister Reg = Op.getReg(); 162681ad6265SDimitry Andric 162781ad6265SDimitry Andric if (CSKYMCRegisterClasses[CSKY::FPR32RegClassID].contains(Reg)) { 162881ad6265SDimitry Andric // As the parser couldn't differentiate an FPR64 from an FPR32, coerce the 162981ad6265SDimitry Andric // register from FPR32 to FPR64 if necessary. 163081ad6265SDimitry Andric if (Kind == MCK_FPR64 || Kind == MCK_sFPR64) { 163181ad6265SDimitry Andric Op.Reg.RegNum = convertFPR32ToFPR64(Reg); 163281ad6265SDimitry Andric if (Kind == MCK_sFPR64 && 163381ad6265SDimitry Andric (Op.Reg.RegNum < CSKY::F0_64 || Op.Reg.RegNum > CSKY::F15_64)) 163481ad6265SDimitry Andric return Match_InvalidRegOutOfRange; 163581ad6265SDimitry Andric if (Kind == MCK_FPR64 && 163681ad6265SDimitry Andric (Op.Reg.RegNum < CSKY::F0_64 || Op.Reg.RegNum > CSKY::F31_64)) 163781ad6265SDimitry Andric return Match_InvalidRegOutOfRange; 163881ad6265SDimitry Andric return Match_Success; 163981ad6265SDimitry Andric } 164081ad6265SDimitry Andric } 164181ad6265SDimitry Andric 164281ad6265SDimitry Andric if (CSKYMCRegisterClasses[CSKY::GPRRegClassID].contains(Reg)) { 164381ad6265SDimitry Andric if (Kind == MCK_GPRPair) { 164481ad6265SDimitry Andric Op.Reg.RegNum = MRI->getEncodingValue(Reg) + CSKY::R0_R1; 164581ad6265SDimitry Andric return Match_Success; 164681ad6265SDimitry Andric } 164781ad6265SDimitry Andric } 164881ad6265SDimitry Andric 164981ad6265SDimitry Andric return Match_InvalidOperand; 165081ad6265SDimitry Andric } 1651fe6060f1SDimitry Andric 16520eae32dcSDimitry Andric void CSKYAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) { 16530eae32dcSDimitry Andric MCInst CInst; 16540eae32dcSDimitry Andric bool Res = false; 16550eae32dcSDimitry Andric if (EnableCompressedInst) 1656bdd1243dSDimitry Andric Res = compressInst(CInst, Inst, getSTI()); 16570eae32dcSDimitry Andric if (Res) 16580eae32dcSDimitry Andric ++CSKYNumInstrsCompressed; 16590eae32dcSDimitry Andric S.emitInstruction((Res ? CInst : Inst), getSTI()); 16600eae32dcSDimitry Andric } 16610eae32dcSDimitry Andric 1662fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser() { 1663fe6060f1SDimitry Andric RegisterMCAsmParser<CSKYAsmParser> X(getTheCSKYTarget()); 1664fe6060f1SDimitry Andric } 1665