1bdd1243dSDimitry Andric //===- XtensaAsmParser.cpp - Parse Xtensa assembly to MCInst instructions -===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // The LLVM Compiler Infrastructure 4bdd1243dSDimitry Andric // 5bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 7bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8bdd1243dSDimitry Andric // 9bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 10bdd1243dSDimitry Andric 11*0fca6ea1SDimitry Andric #include "MCTargetDesc/XtensaMCExpr.h" 12bdd1243dSDimitry Andric #include "MCTargetDesc/XtensaMCTargetDesc.h" 13*0fca6ea1SDimitry Andric #include "MCTargetDesc/XtensaTargetStreamer.h" 14bdd1243dSDimitry Andric #include "TargetInfo/XtensaTargetInfo.h" 15bdd1243dSDimitry Andric #include "llvm/ADT/STLExtras.h" 16bdd1243dSDimitry Andric #include "llvm/ADT/StringSwitch.h" 17bdd1243dSDimitry Andric #include "llvm/MC/MCContext.h" 18bdd1243dSDimitry Andric #include "llvm/MC/MCExpr.h" 19bdd1243dSDimitry Andric #include "llvm/MC/MCInst.h" 20bdd1243dSDimitry Andric #include "llvm/MC/MCInstrInfo.h" 21bdd1243dSDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 22bdd1243dSDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 23bdd1243dSDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h" 24bdd1243dSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 25bdd1243dSDimitry Andric #include "llvm/MC/MCStreamer.h" 26bdd1243dSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 27*0fca6ea1SDimitry Andric #include "llvm/MC/MCSymbol.h" 28bdd1243dSDimitry Andric #include "llvm/MC/TargetRegistry.h" 29bdd1243dSDimitry Andric #include "llvm/Support/Casting.h" 30bdd1243dSDimitry Andric 31bdd1243dSDimitry Andric using namespace llvm; 32bdd1243dSDimitry Andric 33bdd1243dSDimitry Andric #define DEBUG_TYPE "xtensa-asm-parser" 34bdd1243dSDimitry Andric 35bdd1243dSDimitry Andric struct XtensaOperand; 36bdd1243dSDimitry Andric 37bdd1243dSDimitry Andric class XtensaAsmParser : public MCTargetAsmParser { 38bdd1243dSDimitry Andric 39bdd1243dSDimitry Andric SMLoc getLoc() const { return getParser().getTok().getLoc(); } 40bdd1243dSDimitry Andric 41*0fca6ea1SDimitry Andric XtensaTargetStreamer &getTargetStreamer() { 42*0fca6ea1SDimitry Andric MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 43*0fca6ea1SDimitry Andric return static_cast<XtensaTargetStreamer &>(TS); 44*0fca6ea1SDimitry Andric } 45*0fca6ea1SDimitry Andric 46*0fca6ea1SDimitry Andric ParseStatus parseDirective(AsmToken DirectiveID) override; 475f757f3fSDimitry Andric bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; 48bdd1243dSDimitry Andric bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 49bdd1243dSDimitry Andric SMLoc NameLoc, OperandVector &Operands) override; 50bdd1243dSDimitry Andric bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 51bdd1243dSDimitry Andric OperandVector &Operands, MCStreamer &Out, 52bdd1243dSDimitry Andric uint64_t &ErrorInfo, 53bdd1243dSDimitry Andric bool MatchingInlineAsm) override; 54bdd1243dSDimitry Andric unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 55bdd1243dSDimitry Andric unsigned Kind) override; 56bdd1243dSDimitry Andric 57*0fca6ea1SDimitry Andric bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, 58*0fca6ea1SDimitry Andric const MCSubtargetInfo *STI); 59*0fca6ea1SDimitry Andric 60bdd1243dSDimitry Andric // Auto-generated instruction matching functions 61bdd1243dSDimitry Andric #define GET_ASSEMBLER_HEADER 62bdd1243dSDimitry Andric #include "XtensaGenAsmMatcher.inc" 63bdd1243dSDimitry Andric 645f757f3fSDimitry Andric ParseStatus parseImmediate(OperandVector &Operands); 655f757f3fSDimitry Andric ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false, 665f757f3fSDimitry Andric bool SR = false); 675f757f3fSDimitry Andric ParseStatus parseOperandWithModifier(OperandVector &Operands); 68bdd1243dSDimitry Andric bool parseOperand(OperandVector &Operands, StringRef Mnemonic, 69bdd1243dSDimitry Andric bool SR = false); 70bdd1243dSDimitry Andric bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name, 71bdd1243dSDimitry Andric SMLoc NameLoc, OperandVector &Operands); 725f757f3fSDimitry Andric ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 73bdd1243dSDimitry Andric SMLoc &EndLoc) override { 745f757f3fSDimitry Andric return ParseStatus::NoMatch; 75bdd1243dSDimitry Andric } 765f757f3fSDimitry Andric ParseStatus parsePCRelTarget(OperandVector &Operands); 77*0fca6ea1SDimitry Andric bool parseLiteralDirective(SMLoc L); 78bdd1243dSDimitry Andric 79bdd1243dSDimitry Andric public: 80bdd1243dSDimitry Andric enum XtensaMatchResultTy { 81bdd1243dSDimitry Andric Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 82bdd1243dSDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES 83bdd1243dSDimitry Andric #include "XtensaGenAsmMatcher.inc" 84bdd1243dSDimitry Andric #undef GET_OPERAND_DIAGNOSTIC_TYPES 85bdd1243dSDimitry Andric }; 86bdd1243dSDimitry Andric 87bdd1243dSDimitry Andric XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 88bdd1243dSDimitry Andric const MCInstrInfo &MII, const MCTargetOptions &Options) 89bdd1243dSDimitry Andric : MCTargetAsmParser(Options, STI, MII) { 90bdd1243dSDimitry Andric setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 91bdd1243dSDimitry Andric } 92bdd1243dSDimitry Andric }; 93bdd1243dSDimitry Andric 94bdd1243dSDimitry Andric // Return true if Expr is in the range [MinValue, MaxValue]. 95bdd1243dSDimitry Andric static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) { 96bdd1243dSDimitry Andric if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { 97bdd1243dSDimitry Andric int64_t Value = CE->getValue(); 98bdd1243dSDimitry Andric return Value >= MinValue && Value <= MaxValue; 99bdd1243dSDimitry Andric } 100bdd1243dSDimitry Andric return false; 101bdd1243dSDimitry Andric } 102bdd1243dSDimitry Andric 103bdd1243dSDimitry Andric struct XtensaOperand : public MCParsedAsmOperand { 104bdd1243dSDimitry Andric 105bdd1243dSDimitry Andric enum KindTy { 106bdd1243dSDimitry Andric Token, 107bdd1243dSDimitry Andric Register, 108bdd1243dSDimitry Andric Immediate, 109bdd1243dSDimitry Andric } Kind; 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric struct RegOp { 112bdd1243dSDimitry Andric unsigned RegNum; 113bdd1243dSDimitry Andric }; 114bdd1243dSDimitry Andric 115bdd1243dSDimitry Andric struct ImmOp { 116bdd1243dSDimitry Andric const MCExpr *Val; 117bdd1243dSDimitry Andric }; 118bdd1243dSDimitry Andric 119bdd1243dSDimitry Andric SMLoc StartLoc, EndLoc; 120bdd1243dSDimitry Andric union { 121bdd1243dSDimitry Andric StringRef Tok; 122bdd1243dSDimitry Andric RegOp Reg; 123bdd1243dSDimitry Andric ImmOp Imm; 124bdd1243dSDimitry Andric }; 125bdd1243dSDimitry Andric 126bdd1243dSDimitry Andric XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 127bdd1243dSDimitry Andric 128bdd1243dSDimitry Andric public: 129bdd1243dSDimitry Andric XtensaOperand(const XtensaOperand &o) : MCParsedAsmOperand() { 130bdd1243dSDimitry Andric Kind = o.Kind; 131bdd1243dSDimitry Andric StartLoc = o.StartLoc; 132bdd1243dSDimitry Andric EndLoc = o.EndLoc; 133bdd1243dSDimitry Andric switch (Kind) { 134bdd1243dSDimitry Andric case Register: 135bdd1243dSDimitry Andric Reg = o.Reg; 136bdd1243dSDimitry Andric break; 137bdd1243dSDimitry Andric case Immediate: 138bdd1243dSDimitry Andric Imm = o.Imm; 139bdd1243dSDimitry Andric break; 140bdd1243dSDimitry Andric case Token: 141bdd1243dSDimitry Andric Tok = o.Tok; 142bdd1243dSDimitry Andric break; 143bdd1243dSDimitry Andric } 144bdd1243dSDimitry Andric } 145bdd1243dSDimitry Andric 146bdd1243dSDimitry Andric bool isToken() const override { return Kind == Token; } 147bdd1243dSDimitry Andric bool isReg() const override { return Kind == Register; } 148bdd1243dSDimitry Andric bool isImm() const override { return Kind == Immediate; } 149bdd1243dSDimitry Andric bool isMem() const override { return false; } 150bdd1243dSDimitry Andric 151bdd1243dSDimitry Andric bool isImm(int64_t MinValue, int64_t MaxValue) const { 152bdd1243dSDimitry Andric return Kind == Immediate && inRange(getImm(), MinValue, MaxValue); 153bdd1243dSDimitry Andric } 154bdd1243dSDimitry Andric 155bdd1243dSDimitry Andric bool isImm8() const { return isImm(-128, 127); } 156bdd1243dSDimitry Andric 157bdd1243dSDimitry Andric bool isImm8_sh8() const { 158bdd1243dSDimitry Andric return isImm(-32768, 32512) && 159bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0); 160bdd1243dSDimitry Andric } 161bdd1243dSDimitry Andric 162bdd1243dSDimitry Andric bool isImm12() const { return isImm(-2048, 2047); } 163bdd1243dSDimitry Andric 164*0fca6ea1SDimitry Andric // Convert MOVI to literal load, when immediate is not in range (-2048, 2047) 165*0fca6ea1SDimitry Andric bool isImm12m() const { return Kind == Immediate; } 166bdd1243dSDimitry Andric 167bdd1243dSDimitry Andric bool isOffset4m32() const { 168bdd1243dSDimitry Andric return isImm(0, 60) && 169bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0); 170bdd1243dSDimitry Andric } 171bdd1243dSDimitry Andric 172bdd1243dSDimitry Andric bool isOffset8m8() const { return isImm(0, 255); } 173bdd1243dSDimitry Andric 174bdd1243dSDimitry Andric bool isOffset8m16() const { 175bdd1243dSDimitry Andric return isImm(0, 510) && 176bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0); 177bdd1243dSDimitry Andric } 178bdd1243dSDimitry Andric 179bdd1243dSDimitry Andric bool isOffset8m32() const { 180bdd1243dSDimitry Andric return isImm(0, 1020) && 181bdd1243dSDimitry Andric ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0); 182bdd1243dSDimitry Andric } 183bdd1243dSDimitry Andric 184bdd1243dSDimitry Andric bool isUimm4() const { return isImm(0, 15); } 185bdd1243dSDimitry Andric 186bdd1243dSDimitry Andric bool isUimm5() const { return isImm(0, 31); } 187bdd1243dSDimitry Andric 188bdd1243dSDimitry Andric bool isImm8n_7() const { return isImm(-8, 7); } 189bdd1243dSDimitry Andric 190bdd1243dSDimitry Andric bool isShimm1_31() const { return isImm(1, 31); } 191bdd1243dSDimitry Andric 192bdd1243dSDimitry Andric bool isImm16_31() const { return isImm(16, 31); } 193bdd1243dSDimitry Andric 194bdd1243dSDimitry Andric bool isImm1_16() const { return isImm(1, 16); } 195bdd1243dSDimitry Andric 196bdd1243dSDimitry Andric bool isB4const() const { 197bdd1243dSDimitry Andric if (Kind != Immediate) 198bdd1243dSDimitry Andric return false; 199bdd1243dSDimitry Andric if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) { 200bdd1243dSDimitry Andric int64_t Value = CE->getValue(); 201bdd1243dSDimitry Andric switch (Value) { 202bdd1243dSDimitry Andric case -1: 203bdd1243dSDimitry Andric case 1: 204bdd1243dSDimitry Andric case 2: 205bdd1243dSDimitry Andric case 3: 206bdd1243dSDimitry Andric case 4: 207bdd1243dSDimitry Andric case 5: 208bdd1243dSDimitry Andric case 6: 209bdd1243dSDimitry Andric case 7: 210bdd1243dSDimitry Andric case 8: 211bdd1243dSDimitry Andric case 10: 212bdd1243dSDimitry Andric case 12: 213bdd1243dSDimitry Andric case 16: 214bdd1243dSDimitry Andric case 32: 215bdd1243dSDimitry Andric case 64: 216bdd1243dSDimitry Andric case 128: 217bdd1243dSDimitry Andric case 256: 218bdd1243dSDimitry Andric return true; 219bdd1243dSDimitry Andric default: 220bdd1243dSDimitry Andric return false; 221bdd1243dSDimitry Andric } 222bdd1243dSDimitry Andric } 223bdd1243dSDimitry Andric return false; 224bdd1243dSDimitry Andric } 225bdd1243dSDimitry Andric 226bdd1243dSDimitry Andric bool isB4constu() const { 227bdd1243dSDimitry Andric if (Kind != Immediate) 228bdd1243dSDimitry Andric return false; 229bdd1243dSDimitry Andric if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) { 230bdd1243dSDimitry Andric int64_t Value = CE->getValue(); 231bdd1243dSDimitry Andric switch (Value) { 232bdd1243dSDimitry Andric case 32768: 233bdd1243dSDimitry Andric case 65536: 234bdd1243dSDimitry Andric case 2: 235bdd1243dSDimitry Andric case 3: 236bdd1243dSDimitry Andric case 4: 237bdd1243dSDimitry Andric case 5: 238bdd1243dSDimitry Andric case 6: 239bdd1243dSDimitry Andric case 7: 240bdd1243dSDimitry Andric case 8: 241bdd1243dSDimitry Andric case 10: 242bdd1243dSDimitry Andric case 12: 243bdd1243dSDimitry Andric case 16: 244bdd1243dSDimitry Andric case 32: 245bdd1243dSDimitry Andric case 64: 246bdd1243dSDimitry Andric case 128: 247bdd1243dSDimitry Andric case 256: 248bdd1243dSDimitry Andric return true; 249bdd1243dSDimitry Andric default: 250bdd1243dSDimitry Andric return false; 251bdd1243dSDimitry Andric } 252bdd1243dSDimitry Andric } 253bdd1243dSDimitry Andric return false; 254bdd1243dSDimitry Andric } 255bdd1243dSDimitry Andric 256bdd1243dSDimitry Andric /// getStartLoc - Gets location of the first token of this operand 257bdd1243dSDimitry Andric SMLoc getStartLoc() const override { return StartLoc; } 258bdd1243dSDimitry Andric /// getEndLoc - Gets location of the last token of this operand 259bdd1243dSDimitry Andric SMLoc getEndLoc() const override { return EndLoc; } 260bdd1243dSDimitry Andric 261*0fca6ea1SDimitry Andric MCRegister getReg() const override { 262bdd1243dSDimitry Andric assert(Kind == Register && "Invalid type access!"); 263bdd1243dSDimitry Andric return Reg.RegNum; 264bdd1243dSDimitry Andric } 265bdd1243dSDimitry Andric 266bdd1243dSDimitry Andric const MCExpr *getImm() const { 267bdd1243dSDimitry Andric assert(Kind == Immediate && "Invalid type access!"); 268bdd1243dSDimitry Andric return Imm.Val; 269bdd1243dSDimitry Andric } 270bdd1243dSDimitry Andric 271bdd1243dSDimitry Andric StringRef getToken() const { 272bdd1243dSDimitry Andric assert(Kind == Token && "Invalid type access!"); 273bdd1243dSDimitry Andric return Tok; 274bdd1243dSDimitry Andric } 275bdd1243dSDimitry Andric 276bdd1243dSDimitry Andric void print(raw_ostream &OS) const override { 277bdd1243dSDimitry Andric switch (Kind) { 278bdd1243dSDimitry Andric case Immediate: 279bdd1243dSDimitry Andric OS << *getImm(); 280bdd1243dSDimitry Andric break; 281bdd1243dSDimitry Andric case Register: 282bdd1243dSDimitry Andric OS << "<register x"; 283bdd1243dSDimitry Andric OS << getReg() << ">"; 284bdd1243dSDimitry Andric break; 285bdd1243dSDimitry Andric case Token: 286bdd1243dSDimitry Andric OS << "'" << getToken() << "'"; 287bdd1243dSDimitry Andric break; 288bdd1243dSDimitry Andric } 289bdd1243dSDimitry Andric } 290bdd1243dSDimitry Andric 291bdd1243dSDimitry Andric static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) { 292bdd1243dSDimitry Andric auto Op = std::make_unique<XtensaOperand>(Token); 293bdd1243dSDimitry Andric Op->Tok = Str; 294bdd1243dSDimitry Andric Op->StartLoc = S; 295bdd1243dSDimitry Andric Op->EndLoc = S; 296bdd1243dSDimitry Andric return Op; 297bdd1243dSDimitry Andric } 298bdd1243dSDimitry Andric 299bdd1243dSDimitry Andric static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S, 300bdd1243dSDimitry Andric SMLoc E) { 301bdd1243dSDimitry Andric auto Op = std::make_unique<XtensaOperand>(Register); 302bdd1243dSDimitry Andric Op->Reg.RegNum = RegNo; 303bdd1243dSDimitry Andric Op->StartLoc = S; 304bdd1243dSDimitry Andric Op->EndLoc = E; 305bdd1243dSDimitry Andric return Op; 306bdd1243dSDimitry Andric } 307bdd1243dSDimitry Andric 308bdd1243dSDimitry Andric static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S, 309bdd1243dSDimitry Andric SMLoc E) { 310bdd1243dSDimitry Andric auto Op = std::make_unique<XtensaOperand>(Immediate); 311bdd1243dSDimitry Andric Op->Imm.Val = Val; 312bdd1243dSDimitry Andric Op->StartLoc = S; 313bdd1243dSDimitry Andric Op->EndLoc = E; 314bdd1243dSDimitry Andric return Op; 315bdd1243dSDimitry Andric } 316bdd1243dSDimitry Andric 317bdd1243dSDimitry Andric void addExpr(MCInst &Inst, const MCExpr *Expr) const { 318bdd1243dSDimitry Andric assert(Expr && "Expr shouldn't be null!"); 319bdd1243dSDimitry Andric int64_t Imm = 0; 320bdd1243dSDimitry Andric bool IsConstant = false; 321bdd1243dSDimitry Andric 322bdd1243dSDimitry Andric if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { 323bdd1243dSDimitry Andric IsConstant = true; 324bdd1243dSDimitry Andric Imm = CE->getValue(); 325bdd1243dSDimitry Andric } 326bdd1243dSDimitry Andric 327bdd1243dSDimitry Andric if (IsConstant) 328bdd1243dSDimitry Andric Inst.addOperand(MCOperand::createImm(Imm)); 329bdd1243dSDimitry Andric else 330bdd1243dSDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr)); 331bdd1243dSDimitry Andric } 332bdd1243dSDimitry Andric 333bdd1243dSDimitry Andric // Used by the TableGen Code 334bdd1243dSDimitry Andric void addRegOperands(MCInst &Inst, unsigned N) const { 335bdd1243dSDimitry Andric assert(N == 1 && "Invalid number of operands!"); 336bdd1243dSDimitry Andric Inst.addOperand(MCOperand::createReg(getReg())); 337bdd1243dSDimitry Andric } 338bdd1243dSDimitry Andric 339bdd1243dSDimitry Andric void addImmOperands(MCInst &Inst, unsigned N) const { 340bdd1243dSDimitry Andric assert(N == 1 && "Invalid number of operands!"); 341bdd1243dSDimitry Andric addExpr(Inst, getImm()); 342bdd1243dSDimitry Andric } 343bdd1243dSDimitry Andric }; 344bdd1243dSDimitry Andric 345bdd1243dSDimitry Andric #define GET_REGISTER_MATCHER 346bdd1243dSDimitry Andric #define GET_MATCHER_IMPLEMENTATION 347bdd1243dSDimitry Andric #include "XtensaGenAsmMatcher.inc" 348bdd1243dSDimitry Andric 349bdd1243dSDimitry Andric unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 350bdd1243dSDimitry Andric unsigned Kind) { 351bdd1243dSDimitry Andric return Match_InvalidOperand; 352bdd1243dSDimitry Andric } 353bdd1243dSDimitry Andric 354bdd1243dSDimitry Andric static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, 355bdd1243dSDimitry Andric uint64_t ErrorInfo) { 356bdd1243dSDimitry Andric if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) { 357bdd1243dSDimitry Andric SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc(); 358bdd1243dSDimitry Andric if (ErrorLoc == SMLoc()) 359bdd1243dSDimitry Andric return Loc; 360bdd1243dSDimitry Andric return ErrorLoc; 361bdd1243dSDimitry Andric } 362bdd1243dSDimitry Andric return Loc; 363bdd1243dSDimitry Andric } 364bdd1243dSDimitry Andric 365*0fca6ea1SDimitry Andric bool XtensaAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 366*0fca6ea1SDimitry Andric MCStreamer &Out, 367*0fca6ea1SDimitry Andric const MCSubtargetInfo *STI) { 368*0fca6ea1SDimitry Andric Inst.setLoc(IDLoc); 369*0fca6ea1SDimitry Andric const unsigned Opcode = Inst.getOpcode(); 370*0fca6ea1SDimitry Andric switch (Opcode) { 371*0fca6ea1SDimitry Andric case Xtensa::L32R: { 372*0fca6ea1SDimitry Andric const MCSymbolRefExpr *OpExpr = 373*0fca6ea1SDimitry Andric static_cast<const MCSymbolRefExpr *>(Inst.getOperand(1).getExpr()); 374*0fca6ea1SDimitry Andric XtensaMCExpr::VariantKind Kind = XtensaMCExpr::VK_Xtensa_None; 375*0fca6ea1SDimitry Andric const MCExpr *NewOpExpr = XtensaMCExpr::create(OpExpr, Kind, getContext()); 376*0fca6ea1SDimitry Andric Inst.getOperand(1).setExpr(NewOpExpr); 377*0fca6ea1SDimitry Andric break; 378*0fca6ea1SDimitry Andric } 379*0fca6ea1SDimitry Andric case Xtensa::MOVI: { 380*0fca6ea1SDimitry Andric XtensaTargetStreamer &TS = this->getTargetStreamer(); 381*0fca6ea1SDimitry Andric 382*0fca6ea1SDimitry Andric // Expand MOVI operand 383*0fca6ea1SDimitry Andric if (!Inst.getOperand(1).isExpr()) { 384*0fca6ea1SDimitry Andric uint64_t ImmOp64 = Inst.getOperand(1).getImm(); 385*0fca6ea1SDimitry Andric int32_t Imm = ImmOp64; 386*0fca6ea1SDimitry Andric if (!isInt<12>(Imm)) { 387*0fca6ea1SDimitry Andric XtensaTargetStreamer &TS = this->getTargetStreamer(); 388*0fca6ea1SDimitry Andric MCInst TmpInst; 389*0fca6ea1SDimitry Andric TmpInst.setLoc(IDLoc); 390*0fca6ea1SDimitry Andric TmpInst.setOpcode(Xtensa::L32R); 391*0fca6ea1SDimitry Andric const MCExpr *Value = MCConstantExpr::create(ImmOp64, getContext()); 392*0fca6ea1SDimitry Andric MCSymbol *Sym = getContext().createTempSymbol(); 393*0fca6ea1SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create( 394*0fca6ea1SDimitry Andric Sym, MCSymbolRefExpr::VK_None, getContext()); 395*0fca6ea1SDimitry Andric const MCExpr *OpExpr = XtensaMCExpr::create( 396*0fca6ea1SDimitry Andric Expr, XtensaMCExpr::VK_Xtensa_None, getContext()); 397*0fca6ea1SDimitry Andric TmpInst.addOperand(Inst.getOperand(0)); 398*0fca6ea1SDimitry Andric MCOperand Op1 = MCOperand::createExpr(OpExpr); 399*0fca6ea1SDimitry Andric TmpInst.addOperand(Op1); 400*0fca6ea1SDimitry Andric TS.emitLiteral(Sym, Value, true, IDLoc); 401*0fca6ea1SDimitry Andric Inst = TmpInst; 402*0fca6ea1SDimitry Andric } 403*0fca6ea1SDimitry Andric } else { 404*0fca6ea1SDimitry Andric MCInst TmpInst; 405*0fca6ea1SDimitry Andric TmpInst.setLoc(IDLoc); 406*0fca6ea1SDimitry Andric TmpInst.setOpcode(Xtensa::L32R); 407*0fca6ea1SDimitry Andric const MCExpr *Value = Inst.getOperand(1).getExpr(); 408*0fca6ea1SDimitry Andric MCSymbol *Sym = getContext().createTempSymbol(); 409*0fca6ea1SDimitry Andric const MCExpr *Expr = 410*0fca6ea1SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 411*0fca6ea1SDimitry Andric const MCExpr *OpExpr = XtensaMCExpr::create( 412*0fca6ea1SDimitry Andric Expr, XtensaMCExpr::VK_Xtensa_None, getContext()); 413*0fca6ea1SDimitry Andric TmpInst.addOperand(Inst.getOperand(0)); 414*0fca6ea1SDimitry Andric MCOperand Op1 = MCOperand::createExpr(OpExpr); 415*0fca6ea1SDimitry Andric TmpInst.addOperand(Op1); 416*0fca6ea1SDimitry Andric Inst = TmpInst; 417*0fca6ea1SDimitry Andric TS.emitLiteral(Sym, Value, true, IDLoc); 418*0fca6ea1SDimitry Andric } 419*0fca6ea1SDimitry Andric break; 420*0fca6ea1SDimitry Andric } 421*0fca6ea1SDimitry Andric default: 422*0fca6ea1SDimitry Andric break; 423*0fca6ea1SDimitry Andric } 424*0fca6ea1SDimitry Andric 425*0fca6ea1SDimitry Andric return true; 426*0fca6ea1SDimitry Andric } 427*0fca6ea1SDimitry Andric 428bdd1243dSDimitry Andric bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 429bdd1243dSDimitry Andric OperandVector &Operands, 430bdd1243dSDimitry Andric MCStreamer &Out, 431bdd1243dSDimitry Andric uint64_t &ErrorInfo, 432bdd1243dSDimitry Andric bool MatchingInlineAsm) { 433bdd1243dSDimitry Andric MCInst Inst; 434bdd1243dSDimitry Andric auto Result = 435bdd1243dSDimitry Andric MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); 436bdd1243dSDimitry Andric 437bdd1243dSDimitry Andric switch (Result) { 438bdd1243dSDimitry Andric default: 439bdd1243dSDimitry Andric break; 440bdd1243dSDimitry Andric case Match_Success: 441*0fca6ea1SDimitry Andric processInstruction(Inst, IDLoc, Out, STI); 442bdd1243dSDimitry Andric Inst.setLoc(IDLoc); 443bdd1243dSDimitry Andric Out.emitInstruction(Inst, getSTI()); 444bdd1243dSDimitry Andric return false; 445bdd1243dSDimitry Andric case Match_MissingFeature: 446bdd1243dSDimitry Andric return Error(IDLoc, "instruction use requires an option to be enabled"); 447bdd1243dSDimitry Andric case Match_MnemonicFail: 448bdd1243dSDimitry Andric return Error(IDLoc, "unrecognized instruction mnemonic"); 449bdd1243dSDimitry Andric case Match_InvalidOperand: { 450bdd1243dSDimitry Andric SMLoc ErrorLoc = IDLoc; 451bdd1243dSDimitry Andric if (ErrorInfo != ~0U) { 452bdd1243dSDimitry Andric if (ErrorInfo >= Operands.size()) 453bdd1243dSDimitry Andric return Error(ErrorLoc, "too few operands for instruction"); 454bdd1243dSDimitry Andric 455bdd1243dSDimitry Andric ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc(); 456bdd1243dSDimitry Andric if (ErrorLoc == SMLoc()) 457bdd1243dSDimitry Andric ErrorLoc = IDLoc; 458bdd1243dSDimitry Andric } 459bdd1243dSDimitry Andric return Error(ErrorLoc, "invalid operand for instruction"); 460bdd1243dSDimitry Andric } 461bdd1243dSDimitry Andric case Match_InvalidImm8: 462bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 463bdd1243dSDimitry Andric "expected immediate in range [-128, 127]"); 464bdd1243dSDimitry Andric case Match_InvalidImm8_sh8: 465bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 466bdd1243dSDimitry Andric "expected immediate in range [-32768, 32512], first 8 bits " 467bdd1243dSDimitry Andric "should be zero"); 468bdd1243dSDimitry Andric case Match_InvalidB4const: 469bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 470bdd1243dSDimitry Andric "expected b4const immediate"); 471bdd1243dSDimitry Andric case Match_InvalidB4constu: 472bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 473bdd1243dSDimitry Andric "expected b4constu immediate"); 474bdd1243dSDimitry Andric case Match_InvalidImm12: 475bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 476bdd1243dSDimitry Andric "expected immediate in range [-2048, 2047]"); 477bdd1243dSDimitry Andric case Match_InvalidImm12m: 478bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 479bdd1243dSDimitry Andric "expected immediate in range [-2048, 2047]"); 480bdd1243dSDimitry Andric case Match_InvalidImm1_16: 481bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 482bdd1243dSDimitry Andric "expected immediate in range [1, 16]"); 483bdd1243dSDimitry Andric case Match_InvalidShimm1_31: 484bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 485bdd1243dSDimitry Andric "expected immediate in range [1, 31]"); 486bdd1243dSDimitry Andric case Match_InvalidUimm4: 487bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 488bdd1243dSDimitry Andric "expected immediate in range [0, 15]"); 489bdd1243dSDimitry Andric case Match_InvalidUimm5: 490bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 491bdd1243dSDimitry Andric "expected immediate in range [0, 31]"); 492bdd1243dSDimitry Andric case Match_InvalidOffset8m8: 493bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 494bdd1243dSDimitry Andric "expected immediate in range [0, 255]"); 495bdd1243dSDimitry Andric case Match_InvalidOffset8m16: 496bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 497bdd1243dSDimitry Andric "expected immediate in range [0, 510], first bit " 498bdd1243dSDimitry Andric "should be zero"); 499bdd1243dSDimitry Andric case Match_InvalidOffset8m32: 500bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 501bdd1243dSDimitry Andric "expected immediate in range [0, 1020], first 2 bits " 502bdd1243dSDimitry Andric "should be zero"); 503bdd1243dSDimitry Andric case Match_InvalidOffset4m32: 504bdd1243dSDimitry Andric return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), 505bdd1243dSDimitry Andric "expected immediate in range [0, 60], first 2 bits " 506bdd1243dSDimitry Andric "should be zero"); 507bdd1243dSDimitry Andric } 508bdd1243dSDimitry Andric 509bdd1243dSDimitry Andric report_fatal_error("Unknown match type detected!"); 510bdd1243dSDimitry Andric } 511bdd1243dSDimitry Andric 5125f757f3fSDimitry Andric ParseStatus XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) { 513bdd1243dSDimitry Andric MCAsmParser &Parser = getParser(); 514bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "parsePCRelTarget\n"); 515bdd1243dSDimitry Andric 516bdd1243dSDimitry Andric SMLoc S = getLexer().getLoc(); 517bdd1243dSDimitry Andric 518bdd1243dSDimitry Andric // Expressions are acceptable 519bdd1243dSDimitry Andric const MCExpr *Expr = nullptr; 520bdd1243dSDimitry Andric if (Parser.parseExpression(Expr)) { 521bdd1243dSDimitry Andric // We have no way of knowing if a symbol was consumed so we must ParseFail 5225f757f3fSDimitry Andric return ParseStatus::Failure; 523bdd1243dSDimitry Andric } 524bdd1243dSDimitry Andric 525bdd1243dSDimitry Andric // Currently not support constants 5265f757f3fSDimitry Andric if (Expr->getKind() == MCExpr::ExprKind::Constant) 5275f757f3fSDimitry Andric return Error(getLoc(), "unknown operand"); 528bdd1243dSDimitry Andric 529bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc())); 5305f757f3fSDimitry Andric return ParseStatus::Success; 531bdd1243dSDimitry Andric } 532bdd1243dSDimitry Andric 5335f757f3fSDimitry Andric bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, 534bdd1243dSDimitry Andric SMLoc &EndLoc) { 535bdd1243dSDimitry Andric const AsmToken &Tok = getParser().getTok(); 536bdd1243dSDimitry Andric StartLoc = Tok.getLoc(); 537bdd1243dSDimitry Andric EndLoc = Tok.getEndLoc(); 5385f757f3fSDimitry Andric Reg = Xtensa::NoRegister; 539bdd1243dSDimitry Andric StringRef Name = getLexer().getTok().getIdentifier(); 540bdd1243dSDimitry Andric 541bdd1243dSDimitry Andric if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) { 542bdd1243dSDimitry Andric getParser().Lex(); // Eat identifier token. 543bdd1243dSDimitry Andric return false; 544bdd1243dSDimitry Andric } 545bdd1243dSDimitry Andric 546bdd1243dSDimitry Andric return Error(StartLoc, "invalid register name"); 547bdd1243dSDimitry Andric } 548bdd1243dSDimitry Andric 5495f757f3fSDimitry Andric ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands, 550bdd1243dSDimitry Andric bool AllowParens, bool SR) { 551bdd1243dSDimitry Andric SMLoc FirstS = getLoc(); 552bdd1243dSDimitry Andric bool HadParens = false; 553bdd1243dSDimitry Andric AsmToken Buf[2]; 554bdd1243dSDimitry Andric StringRef RegName; 555bdd1243dSDimitry Andric 556bdd1243dSDimitry Andric // If this a parenthesised register name is allowed, parse it atomically 557bdd1243dSDimitry Andric if (AllowParens && getLexer().is(AsmToken::LParen)) { 558bdd1243dSDimitry Andric size_t ReadCount = getLexer().peekTokens(Buf); 559bdd1243dSDimitry Andric if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) { 560bdd1243dSDimitry Andric if ((Buf[0].getKind() == AsmToken::Integer) && (!SR)) 5615f757f3fSDimitry Andric return ParseStatus::NoMatch; 562bdd1243dSDimitry Andric HadParens = true; 563bdd1243dSDimitry Andric getParser().Lex(); // Eat '(' 564bdd1243dSDimitry Andric } 565bdd1243dSDimitry Andric } 566bdd1243dSDimitry Andric 567bdd1243dSDimitry Andric unsigned RegNo = 0; 568bdd1243dSDimitry Andric 569bdd1243dSDimitry Andric switch (getLexer().getKind()) { 570bdd1243dSDimitry Andric default: 5715f757f3fSDimitry Andric return ParseStatus::NoMatch; 572bdd1243dSDimitry Andric case AsmToken::Integer: 573bdd1243dSDimitry Andric if (!SR) 5745f757f3fSDimitry Andric return ParseStatus::NoMatch; 575*0fca6ea1SDimitry Andric RegName = getLexer().getTok().getString(); 576bdd1243dSDimitry Andric RegNo = MatchRegisterName(RegName); 577bdd1243dSDimitry Andric if (RegNo == 0) 578bdd1243dSDimitry Andric RegNo = MatchRegisterAltName(RegName); 579bdd1243dSDimitry Andric break; 580bdd1243dSDimitry Andric case AsmToken::Identifier: 581bdd1243dSDimitry Andric RegName = getLexer().getTok().getIdentifier(); 582bdd1243dSDimitry Andric RegNo = MatchRegisterName(RegName); 583bdd1243dSDimitry Andric if (RegNo == 0) 584bdd1243dSDimitry Andric RegNo = MatchRegisterAltName(RegName); 585bdd1243dSDimitry Andric break; 586bdd1243dSDimitry Andric } 587bdd1243dSDimitry Andric 588bdd1243dSDimitry Andric if (RegNo == 0) { 589bdd1243dSDimitry Andric if (HadParens) 590bdd1243dSDimitry Andric getLexer().UnLex(Buf[0]); 5915f757f3fSDimitry Andric return ParseStatus::NoMatch; 592bdd1243dSDimitry Andric } 593bdd1243dSDimitry Andric if (HadParens) 594bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken("(", FirstS)); 595bdd1243dSDimitry Andric SMLoc S = getLoc(); 596bdd1243dSDimitry Andric SMLoc E = getParser().getTok().getEndLoc(); 597bdd1243dSDimitry Andric getLexer().Lex(); 598bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createReg(RegNo, S, E)); 599bdd1243dSDimitry Andric 600bdd1243dSDimitry Andric if (HadParens) { 601bdd1243dSDimitry Andric getParser().Lex(); // Eat ')' 602bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken(")", getLoc())); 603bdd1243dSDimitry Andric } 604bdd1243dSDimitry Andric 6055f757f3fSDimitry Andric return ParseStatus::Success; 606bdd1243dSDimitry Andric } 607bdd1243dSDimitry Andric 6085f757f3fSDimitry Andric ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) { 609bdd1243dSDimitry Andric SMLoc S = getLoc(); 610bdd1243dSDimitry Andric SMLoc E; 611bdd1243dSDimitry Andric const MCExpr *Res; 612bdd1243dSDimitry Andric 613bdd1243dSDimitry Andric switch (getLexer().getKind()) { 614bdd1243dSDimitry Andric default: 6155f757f3fSDimitry Andric return ParseStatus::NoMatch; 616bdd1243dSDimitry Andric case AsmToken::LParen: 617bdd1243dSDimitry Andric case AsmToken::Minus: 618bdd1243dSDimitry Andric case AsmToken::Plus: 619bdd1243dSDimitry Andric case AsmToken::Tilde: 620bdd1243dSDimitry Andric case AsmToken::Integer: 621bdd1243dSDimitry Andric case AsmToken::String: 622bdd1243dSDimitry Andric if (getParser().parseExpression(Res)) 6235f757f3fSDimitry Andric return ParseStatus::Failure; 624bdd1243dSDimitry Andric break; 625bdd1243dSDimitry Andric case AsmToken::Identifier: { 626bdd1243dSDimitry Andric StringRef Identifier; 627bdd1243dSDimitry Andric if (getParser().parseIdentifier(Identifier)) 6285f757f3fSDimitry Andric return ParseStatus::Failure; 629bdd1243dSDimitry Andric 630bdd1243dSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 631bdd1243dSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 632bdd1243dSDimitry Andric break; 633bdd1243dSDimitry Andric } 634bdd1243dSDimitry Andric case AsmToken::Percent: 635bdd1243dSDimitry Andric return parseOperandWithModifier(Operands); 636bdd1243dSDimitry Andric } 637bdd1243dSDimitry Andric 638bdd1243dSDimitry Andric E = SMLoc::getFromPointer(S.getPointer() - 1); 639bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createImm(Res, S, E)); 6405f757f3fSDimitry Andric return ParseStatus::Success; 641bdd1243dSDimitry Andric } 642bdd1243dSDimitry Andric 6435f757f3fSDimitry Andric ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) { 6445f757f3fSDimitry Andric return ParseStatus::Failure; 645bdd1243dSDimitry Andric } 646bdd1243dSDimitry Andric 647bdd1243dSDimitry Andric /// Looks at a token type and creates the relevant operand 648bdd1243dSDimitry Andric /// from this information, adding to Operands. 649bdd1243dSDimitry Andric /// If operand was parsed, returns false, else true. 650bdd1243dSDimitry Andric bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic, 651bdd1243dSDimitry Andric bool SR) { 652bdd1243dSDimitry Andric // Check if the current operand has a custom associated parser, if so, try to 653bdd1243dSDimitry Andric // custom parse the operand, or fallback to the general approach. 6545f757f3fSDimitry Andric ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic); 6555f757f3fSDimitry Andric if (Res.isSuccess()) 656bdd1243dSDimitry Andric return false; 657bdd1243dSDimitry Andric 658bdd1243dSDimitry Andric // If there wasn't a custom match, try the generic matcher below. Otherwise, 659bdd1243dSDimitry Andric // there was a match, but an error occurred, in which case, just return that 660bdd1243dSDimitry Andric // the operand parsing failed. 6615f757f3fSDimitry Andric if (Res.isFailure()) 662bdd1243dSDimitry Andric return true; 663bdd1243dSDimitry Andric 664bdd1243dSDimitry Andric // Attempt to parse token as register 6655f757f3fSDimitry Andric if (parseRegister(Operands, true, SR).isSuccess()) 666bdd1243dSDimitry Andric return false; 667bdd1243dSDimitry Andric 668bdd1243dSDimitry Andric // Attempt to parse token as an immediate 6695f757f3fSDimitry Andric if (parseImmediate(Operands).isSuccess()) 670bdd1243dSDimitry Andric return false; 671bdd1243dSDimitry Andric 672bdd1243dSDimitry Andric // Finally we have exhausted all options and must declare defeat. 6735f757f3fSDimitry Andric return Error(getLoc(), "unknown operand"); 674bdd1243dSDimitry Andric } 675bdd1243dSDimitry Andric 676bdd1243dSDimitry Andric bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info, 677bdd1243dSDimitry Andric StringRef Name, SMLoc NameLoc, 678bdd1243dSDimitry Andric OperandVector &Operands) { 6795f757f3fSDimitry Andric if ((Name.starts_with("wsr.") || Name.starts_with("rsr.") || 6805f757f3fSDimitry Andric Name.starts_with("xsr.")) && 681bdd1243dSDimitry Andric (Name.size() > 4)) { 682bdd1243dSDimitry Andric // Parse case when instruction name is concatenated with SR register 683bdd1243dSDimitry Andric // name, like "wsr.sar a1" 684bdd1243dSDimitry Andric 685bdd1243dSDimitry Andric // First operand is token for instruction 686bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc)); 687bdd1243dSDimitry Andric 688bdd1243dSDimitry Andric StringRef RegName = Name.drop_front(4); 689bdd1243dSDimitry Andric unsigned RegNo = MatchRegisterName(RegName); 690bdd1243dSDimitry Andric 691bdd1243dSDimitry Andric if (RegNo == 0) 692bdd1243dSDimitry Andric RegNo = MatchRegisterAltName(RegName); 693bdd1243dSDimitry Andric 6945f757f3fSDimitry Andric if (RegNo == 0) 6955f757f3fSDimitry Andric return Error(NameLoc, "invalid register name"); 696bdd1243dSDimitry Andric 697bdd1243dSDimitry Andric // Parse operand 698bdd1243dSDimitry Andric if (parseOperand(Operands, Name)) 699bdd1243dSDimitry Andric return true; 700bdd1243dSDimitry Andric 701bdd1243dSDimitry Andric SMLoc S = getLoc(); 702bdd1243dSDimitry Andric SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 703bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createReg(RegNo, S, E)); 704bdd1243dSDimitry Andric } else { 705bdd1243dSDimitry Andric // First operand is token for instruction 706bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken(Name, NameLoc)); 707bdd1243dSDimitry Andric 708bdd1243dSDimitry Andric // Parse first operand 709bdd1243dSDimitry Andric if (parseOperand(Operands, Name)) 710bdd1243dSDimitry Andric return true; 711bdd1243dSDimitry Andric 71206c3fb27SDimitry Andric if (!parseOptionalToken(AsmToken::Comma)) { 713bdd1243dSDimitry Andric SMLoc Loc = getLexer().getLoc(); 714bdd1243dSDimitry Andric getParser().eatToEndOfStatement(); 715bdd1243dSDimitry Andric return Error(Loc, "unexpected token"); 716bdd1243dSDimitry Andric } 717bdd1243dSDimitry Andric 718bdd1243dSDimitry Andric // Parse second operand 719bdd1243dSDimitry Andric if (parseOperand(Operands, Name, true)) 720bdd1243dSDimitry Andric return true; 721bdd1243dSDimitry Andric } 722bdd1243dSDimitry Andric 723bdd1243dSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) { 724bdd1243dSDimitry Andric SMLoc Loc = getLexer().getLoc(); 725bdd1243dSDimitry Andric getParser().eatToEndOfStatement(); 726bdd1243dSDimitry Andric return Error(Loc, "unexpected token"); 727bdd1243dSDimitry Andric } 728bdd1243dSDimitry Andric 729bdd1243dSDimitry Andric getParser().Lex(); // Consume the EndOfStatement. 730bdd1243dSDimitry Andric return false; 731bdd1243dSDimitry Andric } 732bdd1243dSDimitry Andric 733bdd1243dSDimitry Andric bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info, 734bdd1243dSDimitry Andric StringRef Name, SMLoc NameLoc, 735bdd1243dSDimitry Andric OperandVector &Operands) { 7365f757f3fSDimitry Andric if (Name.starts_with("wsr") || Name.starts_with("rsr") || 7375f757f3fSDimitry Andric Name.starts_with("xsr")) { 738bdd1243dSDimitry Andric return ParseInstructionWithSR(Info, Name, NameLoc, Operands); 739bdd1243dSDimitry Andric } 740bdd1243dSDimitry Andric 741bdd1243dSDimitry Andric // First operand is token for instruction 742bdd1243dSDimitry Andric Operands.push_back(XtensaOperand::createToken(Name, NameLoc)); 743bdd1243dSDimitry Andric 744bdd1243dSDimitry Andric // If there are no more operands, then finish 745bdd1243dSDimitry Andric if (getLexer().is(AsmToken::EndOfStatement)) 746bdd1243dSDimitry Andric return false; 747bdd1243dSDimitry Andric 748bdd1243dSDimitry Andric // Parse first operand 749bdd1243dSDimitry Andric if (parseOperand(Operands, Name)) 750bdd1243dSDimitry Andric return true; 751bdd1243dSDimitry Andric 752bdd1243dSDimitry Andric // Parse until end of statement, consuming commas between operands 75306c3fb27SDimitry Andric while (parseOptionalToken(AsmToken::Comma)) 754bdd1243dSDimitry Andric if (parseOperand(Operands, Name)) 755bdd1243dSDimitry Andric return true; 756bdd1243dSDimitry Andric 757bdd1243dSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) { 758bdd1243dSDimitry Andric SMLoc Loc = getLexer().getLoc(); 759bdd1243dSDimitry Andric getParser().eatToEndOfStatement(); 760bdd1243dSDimitry Andric return Error(Loc, "unexpected token"); 761bdd1243dSDimitry Andric } 762bdd1243dSDimitry Andric 763bdd1243dSDimitry Andric getParser().Lex(); // Consume the EndOfStatement. 764bdd1243dSDimitry Andric return false; 765bdd1243dSDimitry Andric } 766bdd1243dSDimitry Andric 767*0fca6ea1SDimitry Andric bool XtensaAsmParser::parseLiteralDirective(SMLoc L) { 768*0fca6ea1SDimitry Andric MCAsmParser &Parser = getParser(); 769*0fca6ea1SDimitry Andric const MCExpr *Value; 770*0fca6ea1SDimitry Andric SMLoc LiteralLoc = getLexer().getLoc(); 771*0fca6ea1SDimitry Andric XtensaTargetStreamer &TS = this->getTargetStreamer(); 772*0fca6ea1SDimitry Andric 773*0fca6ea1SDimitry Andric if (Parser.parseExpression(Value)) 774*0fca6ea1SDimitry Andric return true; 775*0fca6ea1SDimitry Andric 776*0fca6ea1SDimitry Andric const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Value); 777*0fca6ea1SDimitry Andric 778*0fca6ea1SDimitry Andric if (!SE) 779*0fca6ea1SDimitry Andric return Error(LiteralLoc, "literal label must be a symbol"); 780*0fca6ea1SDimitry Andric 781*0fca6ea1SDimitry Andric if (Parser.parseComma()) 782*0fca6ea1SDimitry Andric return true; 783*0fca6ea1SDimitry Andric 784*0fca6ea1SDimitry Andric SMLoc OpcodeLoc = getLexer().getLoc(); 785*0fca6ea1SDimitry Andric if (parseOptionalToken(AsmToken::EndOfStatement)) 786*0fca6ea1SDimitry Andric return Error(OpcodeLoc, "expected value"); 787*0fca6ea1SDimitry Andric 788*0fca6ea1SDimitry Andric if (Parser.parseExpression(Value)) 789*0fca6ea1SDimitry Andric return true; 790*0fca6ea1SDimitry Andric 791*0fca6ea1SDimitry Andric if (parseEOL()) 792*0fca6ea1SDimitry Andric return true; 793*0fca6ea1SDimitry Andric 794*0fca6ea1SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(SE->getSymbol().getName()); 795*0fca6ea1SDimitry Andric 796*0fca6ea1SDimitry Andric TS.emitLiteral(Sym, Value, true, LiteralLoc); 797*0fca6ea1SDimitry Andric 798*0fca6ea1SDimitry Andric return false; 799*0fca6ea1SDimitry Andric } 800*0fca6ea1SDimitry Andric 801*0fca6ea1SDimitry Andric ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) { 802*0fca6ea1SDimitry Andric StringRef IDVal = DirectiveID.getString(); 803*0fca6ea1SDimitry Andric SMLoc Loc = getLexer().getLoc(); 804*0fca6ea1SDimitry Andric 805*0fca6ea1SDimitry Andric if (IDVal == ".literal_position") { 806*0fca6ea1SDimitry Andric XtensaTargetStreamer &TS = this->getTargetStreamer(); 807*0fca6ea1SDimitry Andric TS.emitLiteralPosition(); 808*0fca6ea1SDimitry Andric return parseEOL(); 809*0fca6ea1SDimitry Andric } 810*0fca6ea1SDimitry Andric 811*0fca6ea1SDimitry Andric if (IDVal == ".literal") { 812*0fca6ea1SDimitry Andric return parseLiteralDirective(Loc); 813*0fca6ea1SDimitry Andric } 814*0fca6ea1SDimitry Andric 815*0fca6ea1SDimitry Andric return ParseStatus::NoMatch; 816*0fca6ea1SDimitry Andric } 817*0fca6ea1SDimitry Andric 818bdd1243dSDimitry Andric // Force static initialization. 819bdd1243dSDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() { 820bdd1243dSDimitry Andric RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget()); 821bdd1243dSDimitry Andric } 822