diff options
Diffstat (limited to 'llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
-rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 1636 |
1 files changed, 932 insertions, 704 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 95e7d09ce0c..2b80d3f03de 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -23,7 +23,6 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/TargetRegistry.h" @@ -58,6 +57,7 @@ private: namespace { class MipsAsmParser : public MCTargetAsmParser { + MipsTargetStreamer &getTargetStreamer() { MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer(); return static_cast<MipsTargetStreamer &>(TS); @@ -66,6 +66,7 @@ class MipsAsmParser : public MCTargetAsmParser { MCSubtargetInfo &STI; MCAsmParser &Parser; MipsAssemblerOptions Options; + bool hasConsumedDollar; #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" @@ -75,15 +76,8 @@ class MipsAsmParser : public MCTargetAsmParser { MCStreamer &Out, unsigned &ErrorInfo, bool MatchingInlineAsm); - /// Parse a register as used in CFI directives bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); - bool ParseParenSuffix(StringRef Name, - SmallVectorImpl<MCParsedAsmOperand *> &Operands); - - bool ParseBracketSuffix(StringRef Name, - SmallVectorImpl<MCParsedAsmOperand *> &Operands); - bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand *> &Operands); @@ -91,36 +85,95 @@ class MipsAsmParser : public MCTargetAsmParser { bool ParseDirective(AsmToken DirectiveID); MipsAsmParser::OperandMatchResultTy + parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind); + + MipsAsmParser::OperandMatchResultTy + parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind); + + MipsAsmParser::OperandMatchResultTy + parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind); + + MipsAsmParser::OperandMatchResultTy parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands); - MipsAsmParser::OperandMatchResultTy MatchAnyRegisterNameWithoutDollar( - SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier, - SMLoc S); + bool parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind); + + MipsAsmParser::OperandMatchResultTy + parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseFGRH32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - ParseAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands, - SMLoc S); + parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + parseMSA128BRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - ParseJumpTarget(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + parseMSA128HRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseMSA128WRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseMSA128DRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseMSA128CtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands); - bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + unsigned RegKind); bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &, StringRef Mnemonic); + int tryParseRegister(bool is64BitReg); + + bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + bool is64BitReg); + bool needsExpansion(MCInst &Inst); void expandInstruction(MCInst &Inst, SMLoc IDLoc, @@ -182,6 +235,8 @@ class MipsAsmParser : public MCTargetAsmParser { bool eatComma(StringRef ErrorStr); + int matchRegisterName(StringRef Symbol, bool is64BitReg); + int matchCPURegisterName(StringRef Symbol); int matchRegisterByNumber(unsigned RegNum, unsigned RegClass); @@ -196,12 +251,17 @@ class MipsAsmParser : public MCTargetAsmParser { int matchMSA128CtrlRegisterName(StringRef Name); + int regKindToRegClass(int RegKind); + unsigned getReg(int RC, int RegNo); unsigned getGPR(int RegNo); int getATReg(); + // Warn if RegNo is the current assembler temporary. + void warnIfAssemblerTemporary(int RegNo); + bool processInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); @@ -227,7 +287,8 @@ class MipsAsmParser : public MCTargetAsmParser { public: MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII) - : MCTargetAsmParser(), STI(sti), Parser(parser) { + : MCTargetAsmParser(), STI(sti), Parser(parser), + hasConsumedDollar(false) { // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); @@ -240,9 +301,6 @@ public: MCAsmParser &getParser() const { return Parser; } MCAsmLexer &getLexer() const { return Parser.getLexer(); } - - /// Warn if RegNo is the current assembler temporary. - void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc); }; } @@ -251,56 +309,53 @@ namespace { /// MipsOperand - Instances of this class represent a parsed Mips machine /// instruction. class MipsOperand : public MCParsedAsmOperand { + public: - /// Broad categories of register classes - /// The exact class is finalized by the render method. - enum RegKind { - RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64()) - RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and - /// isFP64()) - RegKind_FCC = 4, /// FCC - RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which) - RegKind_MSACtrl = 16, /// MSA control registers - RegKind_COP2 = 32, /// COP2 - RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on - /// context). - RegKind_CCR = 128, /// CCR - RegKind_HWRegs = 256, /// HWRegs - - /// Potentially any (e.g. $1) - RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 | - RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC | - RegKind_CCR | RegKind_HWRegs + enum RegisterKind { + Kind_None, + Kind_GPR32, + Kind_GPR64, + Kind_HWRegs, + Kind_FGR32Regs, + Kind_FGRH32Regs, + Kind_FGR64Regs, + Kind_AFGR64Regs, + Kind_CCRRegs, + Kind_FCCRegs, + Kind_ACC64DSP, + Kind_LO32DSP, + Kind_HI32DSP, + Kind_COP2, + Kind_MSA128BRegs, + Kind_MSA128HRegs, + Kind_MSA128WRegs, + Kind_MSA128DRegs, + Kind_MSA128CtrlRegs }; private: enum KindTy { + k_CondCode, + k_CoprocNum, k_Immediate, k_Memory, - k_PhysRegister, - k_RegisterIndex, - k_Token + k_PostIndexRegister, + k_Register, + k_PtrReg, + k_Token, + k_LSAImm } Kind; - MipsOperand(KindTy K, MipsAsmParser &Parser) - : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {} - - /// For diagnostics, and checking the assembler temporary - MipsAsmParser &AsmParser; + MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} struct Token { const char *Data; unsigned Length; }; - struct PhysRegOp { - unsigned Num; /// Register Number - }; - - struct RegIdxOp { - unsigned Index; /// Index into the register class - RegKind Kind; /// Bitfield of the kinds it could possibly be - const MCRegisterInfo *RegInfo; + struct RegOp { + unsigned RegNum; + RegisterKind Kind; }; struct ImmOp { @@ -308,161 +363,30 @@ private: }; struct MemOp { - MipsOperand *Base; + unsigned Base; const MCExpr *Off; }; union { struct Token Tok; - struct PhysRegOp PhysReg; - struct RegIdxOp RegIdx; + struct RegOp Reg; struct ImmOp Imm; struct MemOp Mem; }; SMLoc StartLoc, EndLoc; - /// Internal constructor for register kinds - static MipsOperand *CreateReg(unsigned Index, RegKind RegKind, - const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, - MipsAsmParser &Parser) { - MipsOperand *Op = new MipsOperand(k_RegisterIndex, Parser); - Op->RegIdx.Index = Index; - Op->RegIdx.RegInfo = RegInfo; - Op->RegIdx.Kind = RegKind; - Op->StartLoc = S; - Op->EndLoc = E; - return Op; - } - public: - /// Coerce the register to GPR32 and return the real register for the current - /// target. - unsigned getGPR32Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); - AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc); - unsigned ClassID = Mips::GPR32RegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to GPR64 and return the real register for the current - /// target. - unsigned getGPR64Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); - unsigned ClassID = Mips::GPR64RegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); + void addRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getReg())); } -private: - /// Coerce the register to AFGR64 and return the real register for the current - /// target. - unsigned getAFGR64Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); - if (RegIdx.Index % 2 != 0) - AsmParser.Warning(StartLoc, "Float register should be even."); - return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID) - .getRegister(RegIdx.Index / 2); - } - - /// Coerce the register to FGR64 and return the real register for the current - /// target. - unsigned getFGR64Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); - return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID) - .getRegister(RegIdx.Index); - } - - /// Coerce the register to FGR32 and return the real register for the current - /// target. - unsigned getFGR32Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); - return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID) - .getRegister(RegIdx.Index); - } - - /// Coerce the register to FGRH32 and return the real register for the current - /// target. - unsigned getFGRH32Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); - return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID) - .getRegister(RegIdx.Index); - } - - /// Coerce the register to FCC and return the real register for the current - /// target. - unsigned getFCCReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!"); - return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID) - .getRegister(RegIdx.Index); - } - - /// Coerce the register to MSA128 and return the real register for the current - /// target. - unsigned getMSA128Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!"); - // It doesn't matter which of the MSA128[BHWD] classes we use. They are all - // identical - unsigned ClassID = Mips::MSA128BRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to MSACtrl and return the real register for the - /// current target. - unsigned getMSACtrlReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!"); - unsigned ClassID = Mips::MSACtrlRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to COP2 and return the real register for the - /// current target. - unsigned getCOP2Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!"); - unsigned ClassID = Mips::COP2RegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to ACC64DSP and return the real register for the - /// current target. - unsigned getACC64DSPReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); - unsigned ClassID = Mips::ACC64DSPRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to HI32DSP and return the real register for the - /// current target. - unsigned getHI32DSPReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); - unsigned ClassID = Mips::HI32DSPRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to LO32DSP and return the real register for the - /// current target. - unsigned getLO32DSPReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); - unsigned ClassID = Mips::LO32DSPRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to CCR and return the real register for the - /// current target. - unsigned getCCRReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!"); - unsigned ClassID = Mips::CCRRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to HWRegs and return the real register for the - /// current target. - unsigned getHWRegsReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!"); - unsigned ClassID = Mips::HWRegsRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); + void addPtrRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getPtrReg())); } -public: void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediate when possible. Null MCExpr = 0. if (Expr == 0) @@ -473,85 +397,6 @@ public: Inst.addOperand(MCOperand::CreateExpr(Expr)); } - void addRegOperands(MCInst &Inst, unsigned N) const { - llvm_unreachable("Use a custom parser instead"); - } - - void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getGPR32Reg())); - } - - void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getGPR64Reg())); - } - - void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg())); - } - - void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getFGR64Reg())); - } - - void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getFGR32Reg())); - } - - void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg())); - } - - void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getFCCReg())); - } - - void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getMSA128Reg())); - } - - void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg())); - } - - void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getCOP2Reg())); - } - - void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg())); - } - - void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg())); - } - - void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg())); - } - - void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getCCRReg())); - } - - void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getHWRegsReg())); - } - void addImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); const MCExpr *Expr = getImm(); @@ -561,38 +406,19 @@ public: void addMemOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg())); + Inst.addOperand(MCOperand::CreateReg(getMemBase())); const MCExpr *Expr = getMemOff(); addExpr(Inst, Expr); } - bool isReg() const { - // As a special case until we sort out the definition of div/divu, pretend - // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. - if (isGPRAsmReg() && RegIdx.Index == 0) - return true; - - return Kind == k_PhysRegister; - } - bool isRegIdx() const { return Kind == k_RegisterIndex; } + bool isReg() const { return Kind == k_Register; } bool isImm() const { return Kind == k_Immediate; } - bool isConstantImm() const { - return isImm() && dyn_cast<MCConstantExpr>(getImm()); - } - bool isToken() const { - // Note: It's not possible to pretend that other operand kinds are tokens. - // The matcher emitter checks tokens first. - return Kind == k_Token; - } + bool isToken() const { return Kind == k_Token; } bool isMem() const { return Kind == k_Memory; } + bool isPtrReg() const { return Kind == k_PtrReg; } bool isInvNum() const { return Kind == k_Immediate; } - bool isLSAImm() const { - if (!isConstantImm()) - return false; - int64_t Val = getConstantImm(); - return 1 <= Val && Val <= 4; - } + bool isLSAImm() const { return Kind == k_LSAImm; } StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); @@ -600,27 +426,26 @@ public: } unsigned getReg() const { - // As a special case until we sort out the definition of div/divu, pretend - // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. - if (Kind == k_RegisterIndex && RegIdx.Index == 0 && - RegIdx.Kind & RegKind_GPR) - return getGPR32Reg(); // FIXME: GPR64 too + assert((Kind == k_Register) && "Invalid access!"); + return Reg.RegNum; + } - assert(Kind == k_PhysRegister && "Invalid access!"); - return PhysReg.Num; + unsigned getPtrReg() const { + assert((Kind == k_PtrReg) && "Invalid access!"); + return Reg.RegNum; } - const MCExpr *getImm() const { - assert((Kind == k_Immediate) && "Invalid access!"); - return Imm.Val; + void setRegKind(RegisterKind RegKind) { + assert((Kind == k_Register || Kind == k_PtrReg) && "Invalid access!"); + Reg.Kind = RegKind; } - int64_t getConstantImm() const { - const MCExpr *Val = getImm(); - return static_cast<const MCConstantExpr *>(Val)->getValue(); + const MCExpr *getImm() const { + assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!"); + return Imm.Val; } - MipsOperand *getMemBase() const { + unsigned getMemBase() const { assert((Kind == k_Memory) && "Invalid access!"); return Mem.Base; } @@ -630,9 +455,8 @@ public: return Mem.Off; } - static MipsOperand *CreateToken(StringRef Str, SMLoc S, - MipsAsmParser &Parser) { - MipsOperand *Op = new MipsOperand(k_Token, Parser); + static MipsOperand *CreateToken(StringRef Str, SMLoc S) { + MipsOperand *Op = new MipsOperand(k_Token); Op->Tok.Data = Str.data(); Op->Tok.Length = Str.size(); Op->StartLoc = S; @@ -640,75 +464,43 @@ public: return Op; } - /// Create a numeric register (e.g. $1). The exact register remains - /// unresolved until an instruction successfully matches - static MipsOperand *CreateNumericReg(unsigned Index, - const MCRegisterInfo *RegInfo, SMLoc S, - SMLoc E, MipsAsmParser &Parser) { - DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n"); - return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser); - } - - /// Create a register that is definitely a GPR. - /// This is typically only used for named registers such as $gp. - static MipsOperand *CreateGPRReg(unsigned Index, - const MCRegisterInfo *RegInfo, SMLoc S, - SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser); - } - - /// Create a register that is definitely a FGR. - /// This is typically only used for named registers such as $f0. - static MipsOperand *CreateFGRReg(unsigned Index, - const MCRegisterInfo *RegInfo, SMLoc S, - SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser); - } - - /// Create a register that is definitely an FCC. - /// This is typically only used for named registers such as $fcc0. - static MipsOperand *CreateFCCReg(unsigned Index, - const MCRegisterInfo *RegInfo, SMLoc S, - SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser); - } - - /// Create a register that is definitely an ACC. - /// This is typically only used for named registers such as $ac0. - static MipsOperand *CreateACCReg(unsigned Index, - const MCRegisterInfo *RegInfo, SMLoc S, - SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser); + static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { + MipsOperand *Op = new MipsOperand(k_Register); + Op->Reg.RegNum = RegNum; + Op->Reg.Kind = Kind_None; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; } - /// Create a register that is definitely an MSA128. - /// This is typically only used for named registers such as $w0. - static MipsOperand *CreateMSA128Reg(unsigned Index, - const MCRegisterInfo *RegInfo, SMLoc S, - SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser); + static MipsOperand *CreatePtrReg(unsigned RegNum, SMLoc S, SMLoc E) { + MipsOperand *Op = new MipsOperand(k_PtrReg); + Op->Reg.RegNum = RegNum; + Op->Reg.Kind = Kind_None; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; } - /// Create a register that is definitely an MSACtrl. - /// This is typically only used for named registers such as $msaaccess. - static MipsOperand *CreateMSACtrlReg(unsigned Index, - const MCRegisterInfo *RegInfo, SMLoc S, - SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser); + static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { + MipsOperand *Op = new MipsOperand(k_Immediate); + Op->Imm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; } - static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, - MipsAsmParser &Parser) { - MipsOperand *Op = new MipsOperand(k_Immediate, Parser); + static MipsOperand *CreateLSAImm(const MCExpr *Val, SMLoc S, SMLoc E) { + MipsOperand *Op = new MipsOperand(k_LSAImm); Op->Imm.Val = Val; Op->StartLoc = S; Op->EndLoc = E; return Op; } - static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S, - SMLoc E, MipsAsmParser &Parser) { - MipsOperand *Op = new MipsOperand(k_Memory, Parser); + static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S, + SMLoc E) { + MipsOperand *Op = new MipsOperand(k_Memory); Op->Mem.Base = Base; Op->Mem.Off = Off; Op->StartLoc = S; @@ -716,33 +508,79 @@ public: return Op; } - bool isGPRAsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; + bool isGPR32Asm() const { + return Kind == k_Register && Reg.Kind == Kind_GPR32; } - bool isFGRAsmReg() const { - // AFGR64 is $0-$15 but we handle this in getAFGR64() - return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; + void addRegAsmOperands(MCInst &Inst, unsigned N) const { + Inst.addOperand(MCOperand::CreateReg(Reg.RegNum)); } - bool isHWRegsAsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31; + + bool isGPR64Asm() const { + return Kind == k_Register && Reg.Kind == Kind_GPR64; } - bool isCCRAsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31; + + bool isHWRegsAsm() const { + assert((Kind == k_Register) && "Invalid access!"); + return Reg.Kind == Kind_HWRegs; } - bool isFCCAsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7; + + bool isCCRAsm() const { + assert((Kind == k_Register) && "Invalid access!"); + return Reg.Kind == Kind_CCRRegs; + } + + bool isAFGR64Asm() const { + return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs; + } + + bool isFGR64Asm() const { + return Kind == k_Register && Reg.Kind == Kind_FGR64Regs; } - bool isACCAsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3; + + bool isFGR32Asm() const { + return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs; } - bool isCOP2AsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31; + + bool isFGRH32Asm() const { + return (Kind == k_Register) && Reg.Kind == Kind_FGRH32Regs; } - bool isMSA128AsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31; + + bool isFCCRegsAsm() const { + return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs; } - bool isMSACtrlAsmReg() const { - return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7; + + bool isACC64DSPAsm() const { + return Kind == k_Register && Reg.Kind == Kind_ACC64DSP; + } + + bool isLO32DSPAsm() const { + return Kind == k_Register && Reg.Kind == Kind_LO32DSP; + } + + bool isHI32DSPAsm() const { + return Kind == k_Register && Reg.Kind == Kind_HI32DSP; + } + + bool isCOP2Asm() const { return Kind == k_Register && Reg.Kind == Kind_COP2; } + + bool isMSA128BAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128BRegs; + } + + bool isMSA128HAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128HRegs; + } + + bool isMSA128WAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128WRegs; + } + + bool isMSA128DAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128DRegs; + } + + bool isMSA128CRAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128CtrlRegs; } /// getStartLoc - Get the location of the first token of this operand. @@ -751,29 +589,7 @@ public: SMLoc getEndLoc() const { return EndLoc; } virtual void print(raw_ostream &OS) const { - switch (Kind) { - case k_Immediate: - OS << "Imm<"; - Imm.Val->print(OS); - OS << ">"; - break; - case k_Memory: - OS << "Mem<"; - Mem.Base->print(OS); - OS << ", "; - Mem.Off->print(OS); - OS << ">"; - break; - case k_PhysRegister: - OS << "PhysReg<" << PhysReg.Num << ">"; - break; - case k_RegisterIndex: - OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">"; - break; - case k_Token: - OS << Tok.Data; - break; - } + llvm_unreachable("unimplemented!"); } }; // class MipsOperand } // namespace @@ -800,8 +616,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, break; case Mips::BEQ: case Mips::BNE: - case Mips::BEQ_MM: - case Mips::BNE_MM: assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); Offset = Inst.getOperand(2); if (!Offset.isImm()) @@ -819,14 +633,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, case Mips::BLTZAL: case Mips::BC1F: case Mips::BC1T: - case Mips::BGEZ_MM: - case Mips::BGTZ_MM: - case Mips::BLEZ_MM: - case Mips::BLTZ_MM: - case Mips::BGEZAL_MM: - case Mips::BLTZAL_MM: - case Mips::BC1F_MM: - case Mips::BC1T_MM: assert(MCID.getNumOperands() == 2 && "unexpected number of operands"); Offset = Inst.getOperand(1); if (!Offset.isImm()) @@ -1190,13 +996,14 @@ bool MipsAsmParser::MatchAndEmitInstruction( return true; } -void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) { - if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) { - if (RegIndex == 1) - Warning(Loc, "Used $at without \".set noat\""); +void MipsAsmParser::warnIfAssemblerTemporary(int RegNo) { + if ((RegNo != 0) && ((int)Options.getATRegNum() == RegNo)) { + if (RegNo == 1) + Warning(getLexer().getLoc(), "Used $at without \".set noat\""); else - Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" + - Twine(RegIndex) + "\""); + Warning(getLexer().getLoc(), Twine("Used $") + Twine(RegNo) + + " with \".set at=$" + Twine(RegNo) + + "\""); } } @@ -1257,6 +1064,8 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) { .Default(-1); } + warnIfAssemblerTemporary(CC); + return CC; } @@ -1331,6 +1140,59 @@ int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) { return CC; } +int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) { + + int CC; + CC = matchCPURegisterName(Name); + if (CC != -1) + return matchRegisterByNumber(CC, is64BitReg ? Mips::GPR64RegClassID + : Mips::GPR32RegClassID); + CC = matchFPURegisterName(Name); + // TODO: decide about fpu register class + if (CC != -1) + return matchRegisterByNumber(CC, isFP64() ? Mips::FGR64RegClassID + : Mips::FGR32RegClassID); + return matchMSA128RegisterName(Name); +} + +int MipsAsmParser::regKindToRegClass(int RegKind) { + + switch (RegKind) { + case MipsOperand::Kind_GPR32: + return Mips::GPR32RegClassID; + case MipsOperand::Kind_GPR64: + return Mips::GPR64RegClassID; + case MipsOperand::Kind_HWRegs: + return Mips::HWRegsRegClassID; + case MipsOperand::Kind_FGR32Regs: + return Mips::FGR32RegClassID; + case MipsOperand::Kind_FGRH32Regs: + return Mips::FGRH32RegClassID; + case MipsOperand::Kind_FGR64Regs: + return Mips::FGR64RegClassID; + case MipsOperand::Kind_AFGR64Regs: + return Mips::AFGR64RegClassID; + case MipsOperand::Kind_CCRRegs: + return Mips::CCRRegClassID; + case MipsOperand::Kind_ACC64DSP: + return Mips::ACC64DSPRegClassID; + case MipsOperand::Kind_FCCRegs: + return Mips::FCCRegClassID; + case MipsOperand::Kind_MSA128BRegs: + return Mips::MSA128BRegClassID; + case MipsOperand::Kind_MSA128HRegs: + return Mips::MSA128HRegClassID; + case MipsOperand::Kind_MSA128WRegs: + return Mips::MSA128WRegClassID; + case MipsOperand::Kind_MSA128DRegs: + return Mips::MSA128DRegClassID; + case MipsOperand::Kind_MSA128CtrlRegs: + return Mips::MSACtrlRegClassID; + default: + return -1; + } +} + bool MipsAssemblerOptions::setATReg(unsigned Reg) { if (Reg > 31) return false; @@ -1360,14 +1222,45 @@ int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) { getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1) return -1; + if (RegClass == Mips::GPR32RegClassID || RegClass == Mips::GPR64RegClassID) + warnIfAssemblerTemporary(RegNum); + return getReg(RegClass, RegNum); } +int MipsAsmParser::tryParseRegister(bool is64BitReg) { + const AsmToken &Tok = Parser.getTok(); + int RegNum = -1; + + if (Tok.is(AsmToken::Identifier)) { + std::string lowerCase = Tok.getString().lower(); + RegNum = matchRegisterName(lowerCase, is64BitReg); + } else if (Tok.is(AsmToken::Integer)) + RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()), + is64BitReg ? Mips::GPR64RegClassID + : Mips::GPR32RegClassID); + return RegNum; +} + +bool MipsAsmParser::tryParseRegisterOperand( + SmallVectorImpl<MCParsedAsmOperand *> &Operands, bool is64BitReg) { + + SMLoc S = Parser.getTok().getLoc(); + int RegNo = -1; + + RegNo = tryParseRegister(is64BitReg); + if (RegNo == -1) + return true; + + Operands.push_back( + MipsOperand::CreateReg(RegNo, S, Parser.getTok().getLoc())); + Parser.Lex(); // Eat register token. + return false; +} + bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Mnemonic) { - DEBUG(dbgs() << "ParseOperand\n"); - // Check if the current operand has a custom associated parser, if so, try to // custom parse the operand, or fallback to the general approach. OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); @@ -1379,8 +1272,6 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, if (ResTy == MatchOperand_ParseFail) return true; - DEBUG(dbgs() << ".. Generic Parser\n"); - switch (getLexer().getKind()) { default: Error(Parser.getTok().getLoc(), "unexpected token in operand"); @@ -1388,15 +1279,29 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, case AsmToken::Dollar: { // Parse the register. SMLoc S = Parser.getTok().getLoc(); + Parser.Lex(); // Eat dollar token. + // Parse the register operand. + if (!tryParseRegisterOperand(Operands, isGP64())) { + if (getLexer().is(AsmToken::LParen)) { + // Check if it is indexed addressing operand. + Operands.push_back(MipsOperand::CreateToken("(", S)); + Parser.Lex(); // Eat the parenthesis. + if (getLexer().isNot(AsmToken::Dollar)) + return true; - // Almost all registers have been parsed by custom parsers. There is only - // one exception to this. $zero (and it's alias $0) will reach this point - // for div, divu, and similar instructions because it is not an operand - // to the instruction definition but an explicit register. Special case - // this situation for now. - if (ParseAnyRegister(Operands) != MatchOperand_NoMatch) - return false; + Parser.Lex(); // Eat the dollar + if (tryParseRegisterOperand(Operands, isGP64())) + return true; + if (!getLexer().is(AsmToken::RParen)) + return true; + + S = Parser.getTok().getLoc(); + Operands.push_back(MipsOperand::CreateToken(")", S)); + Parser.Lex(); + } + return false; + } // Maybe it is a symbol reference. StringRef Identifier; if (Parser.parseIdentifier(Identifier)) @@ -1408,18 +1313,47 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); - Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this)); + Operands.push_back(MipsOperand::CreateImm(Res, S, E)); return false; } + case AsmToken::Identifier: + // For instruction aliases like "bc1f $Label" dedicated parser will + // eat the '$' sign before failing. So in order to look for appropriate + // label we must check first if we have already consumed '$'. + if (hasConsumedDollar) { + hasConsumedDollar = false; + SMLoc S = Parser.getTok().getLoc(); + StringRef Identifier; + if (Parser.parseIdentifier(Identifier)) + return true; + SMLoc E = + SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier); + // Create a symbol reference. + const MCExpr *Res = + MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); + + Operands.push_back(MipsOperand::CreateImm(Res, S, E)); + return false; + } + // Look for the existing symbol, we should check if + // we need to assign the proper RegisterKind. + if (searchSymbolAlias(Operands, MipsOperand::Kind_None)) + return false; // Else drop to expression parsing. case AsmToken::LParen: case AsmToken::Minus: case AsmToken::Plus: case AsmToken::Integer: case AsmToken::String: { - DEBUG(dbgs() << ".. generic integer\n"); - OperandMatchResultTy ResTy = ParseImm(Operands); - return ResTy != MatchOperand_Success; + // Quoted label names. + const MCExpr *IdVal; + SMLoc S = Parser.getTok().getLoc(); + if (getParser().parseExpression(IdVal)) + return true; + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); + return false; } case AsmToken::Percent: { // It is a symbol reference or constant expression. @@ -1430,7 +1364,7 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); + Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); return false; } // case AsmToken::Percent } // switch(getLexer().getKind()) @@ -1562,27 +1496,9 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { - SmallVector<MCParsedAsmOperand *, 1> Operands; - OperandMatchResultTy ResTy = ParseAnyRegister(Operands); - if (ResTy == MatchOperand_Success) { - assert(Operands.size() == 1); - MipsOperand &Operand = *static_cast<MipsOperand *>(Operands.front()); - StartLoc = Operand.getStartLoc(); - EndLoc = Operand.getEndLoc(); - - // AFAIK, we only support numeric registers and named GPR's in CFI - // directives. - // Don't worry about eating tokens before failing. Using an unrecognised - // register is a parse error. - if (Operand.isGPRAsmReg()) { - // Resolve to GPR32 or GPR64 appropriately. - RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg(); - } - - return (RegNo == (unsigned)-1); - } - - assert(Operands.size() == 0); + StartLoc = Parser.getTok().getLoc(); + RegNo = tryParseRegister(isGP64()); + EndLoc = Parser.getTok().getLoc(); return (RegNo == (unsigned)-1); } @@ -1616,7 +1532,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - DEBUG(dbgs() << "parseMemOperand\n"); + const MCExpr *IdVal = 0; SMLoc S; bool isParenExpr = false; @@ -1639,7 +1555,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( if (Mnemonic->getToken() == "la") { SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); + Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); return MatchOperand_Success; } if (Tok.is(AsmToken::EndOfStatement)) { @@ -1647,9 +1563,8 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); // Zero register assumed, add a memory operand with ZERO as its base. - MipsOperand *Base = MipsOperand::CreateGPRReg( - 0, getContext().getRegisterInfo(), S, E, *this); - Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this)); + Operands.push_back(MipsOperand::CreateMem( + isGP64() ? Mips::ZERO_64 : Mips::ZERO, IdVal, S, E)); return MatchOperand_Success; } Error(Parser.getTok().getLoc(), "'(' expected"); @@ -1659,7 +1574,8 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( Parser.Lex(); // Eat the '(' token. } - Res = ParseAnyRegister(Operands); + Res = parseRegs(Operands, isGP64() ? (int)MipsOperand::Kind_GPR64 + : (int)MipsOperand::Kind_GPR32); if (Res != MatchOperand_Success) return Res; @@ -1677,6 +1593,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( // Replace the register operand with the memory operand. MipsOperand *op = static_cast<MipsOperand *>(Operands.back()); + int RegNo = op->getReg(); // Remove the register from the operands. Operands.pop_back(); // Add the memory operand. @@ -1689,220 +1606,599 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( getContext()); } - Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this)); + Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E)); + delete op; return MatchOperand_Success; } -bool MipsAsmParser::searchSymbolAlias( - SmallVectorImpl<MCParsedAsmOperand *> &Operands) { +bool MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind) { + // If the first token is not '$' we have an error. + if (Parser.getTok().isNot(AsmToken::Dollar)) + return false; - MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier()); - if (Sym) { - SMLoc S = Parser.getTok().getLoc(); - const MCExpr *Expr; - if (Sym->isVariable()) - Expr = Sym->getVariableValue(); - else + SMLoc S = Parser.getTok().getLoc(); + Parser.Lex(); + AsmToken::TokenKind TkKind = getLexer().getKind(); + int Reg; + + if (TkKind == AsmToken::Integer) { + Reg = matchRegisterByNumber(Parser.getTok().getIntVal(), + regKindToRegClass(RegKind)); + if (Reg == -1) return false; - if (Expr->getKind() == MCExpr::SymbolRef) { - const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); - const StringRef DefSymbol = Ref->getSymbol().getName(); - if (DefSymbol.startswith("$")) { - OperandMatchResultTy ResTy = - MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S); - if (ResTy == MatchOperand_Success) - return true; - else if (ResTy == MatchOperand_ParseFail) - llvm_unreachable("Should never ParseFail"); - return false; - } - } else if (Expr->getKind() == MCExpr::Constant) { - Parser.Lex(); - const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr); - MipsOperand *op = - MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this); - Operands.push_back(op); - return true; - } + } else if (TkKind == AsmToken::Identifier) { + if ((Reg = matchCPURegisterName(Parser.getTok().getString().lower())) == -1) + return false; + Reg = getReg(regKindToRegClass(RegKind), Reg); + } else { + return false; } - return false; + + MipsOperand *Op = MipsOperand::CreatePtrReg(Reg, S, Parser.getTok().getLoc()); + Op->setRegKind((MipsOperand::RegisterKind)RegKind); + Operands.push_back(Op); + Parser.Lex(); + return true; } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::MatchAnyRegisterNameWithoutDollar( - SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier, - SMLoc S) { - int Index = matchCPURegisterName(Identifier); - if (Index != -1) { - Parser.Lex(); - Operands.push_back(MipsOperand::CreateGPRReg( - Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); +MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + MipsOperand::RegisterKind RegKind = + isN64() ? MipsOperand::Kind_GPR64 : MipsOperand::Kind_GPR32; + + // Parse index register. + if (!parsePtrReg(Operands, RegKind)) + return MatchOperand_NoMatch; + + // Parse '('. + if (Parser.getTok().isNot(AsmToken::LParen)) + return MatchOperand_NoMatch; + + Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc())); + Parser.Lex(); + + // Parse base register. + if (!parsePtrReg(Operands, RegKind)) + return MatchOperand_NoMatch; + + // Parse ')'. + if (Parser.getTok().isNot(AsmToken::RParen)) + return MatchOperand_NoMatch; + + Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc())); + Parser.Lex(); + + return MatchOperand_Success; +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind) { + MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; + if (getLexer().getKind() == AsmToken::Identifier && !hasConsumedDollar) { + if (searchSymbolAlias(Operands, Kind)) + return MatchOperand_Success; + return MatchOperand_NoMatch; + } + SMLoc S = Parser.getTok().getLoc(); + // If the first token is not '$', we have an error. + if (Parser.getTok().isNot(AsmToken::Dollar) && !hasConsumedDollar) + return MatchOperand_NoMatch; + if (!hasConsumedDollar) { + Parser.Lex(); // Eat the '$' + hasConsumedDollar = true; + } + if (getLexer().getKind() == AsmToken::Identifier) { + int RegNum = -1; + std::string RegName = Parser.getTok().getString().lower(); + // Match register by name + switch (RegKind) { + case MipsOperand::Kind_GPR32: + case MipsOperand::Kind_GPR64: + RegNum = matchCPURegisterName(RegName); + break; + case MipsOperand::Kind_AFGR64Regs: + case MipsOperand::Kind_FGR64Regs: + case MipsOperand::Kind_FGR32Regs: + case MipsOperand::Kind_FGRH32Regs: + RegNum = matchFPURegisterName(RegName); + if (RegKind == MipsOperand::Kind_AFGR64Regs) + RegNum /= 2; + else if (RegKind == MipsOperand::Kind_FGRH32Regs && !isFP64()) + if (RegNum != -1 && RegNum % 2 != 0) + Warning(S, "Float register should be even."); + break; + case MipsOperand::Kind_FCCRegs: + RegNum = matchFCCRegisterName(RegName); + break; + case MipsOperand::Kind_ACC64DSP: + RegNum = matchACRegisterName(RegName); + break; + default: + break; // No match, value is set to -1. + } + // No match found, return _NoMatch to give a chance to other round. + if (RegNum < 0) + return MatchOperand_NoMatch; + + int RegVal = getReg(regKindToRegClass(Kind), RegNum); + if (RegVal == -1) + return MatchOperand_NoMatch; + + MipsOperand *Op = + MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc()); + Op->setRegKind(Kind); + Operands.push_back(Op); + hasConsumedDollar = false; + Parser.Lex(); // Eat the register name. + return MatchOperand_Success; + } else if (getLexer().getKind() == AsmToken::Integer) { + unsigned RegNum = Parser.getTok().getIntVal(); + if (Kind == MipsOperand::Kind_HWRegs) { + if (RegNum != 29) + return MatchOperand_NoMatch; + // Only hwreg 29 is supported, found at index 0. + RegNum = 0; + } + int Reg = matchRegisterByNumber(RegNum, regKindToRegClass(Kind)); + if (Reg == -1) + return MatchOperand_NoMatch; + MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); + Op->setRegKind(Kind); + Operands.push_back(Op); + hasConsumedDollar = false; + Parser.Lex(); // Eat the register number. + if ((RegKind == MipsOperand::Kind_GPR32) && + (getLexer().is(AsmToken::LParen))) { + // Check if it is indexed addressing operand. + Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc())); + Parser.Lex(); // Eat the parenthesis. + if (parseRegs(Operands, RegKind) != MatchOperand_Success) + return MatchOperand_NoMatch; + if (getLexer().isNot(AsmToken::RParen)) + return MatchOperand_NoMatch; + Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc())); + Parser.Lex(); + } return MatchOperand_Success; } + return MatchOperand_NoMatch; +} - Index = matchFPURegisterName(Identifier); - if (Index != -1) { - Parser.Lex(); - Operands.push_back(MipsOperand::CreateFGRReg( - Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); - return MatchOperand_Success; +bool MipsAsmParser::validateMSAIndex(int Val, int RegKind) { + MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; + + if (Val < 0) + return false; + + switch (Kind) { + default: + return false; + case MipsOperand::Kind_MSA128BRegs: + return Val < 16; + case MipsOperand::Kind_MSA128HRegs: + return Val < 8; + case MipsOperand::Kind_MSA128WRegs: + return Val < 4; + case MipsOperand::Kind_MSA128DRegs: + return Val < 2; } +} - Index = matchFCCRegisterName(Identifier); - if (Index != -1) { - Parser.Lex(); - Operands.push_back(MipsOperand::CreateFCCReg( - Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); - return MatchOperand_Success; +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind) { + MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; + SMLoc S = Parser.getTok().getLoc(); + std::string RegName; + + if (Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_NoMatch; + + switch (RegKind) { + default: + return MatchOperand_ParseFail; + case MipsOperand::Kind_MSA128BRegs: + case MipsOperand::Kind_MSA128HRegs: + case MipsOperand::Kind_MSA128WRegs: + case MipsOperand::Kind_MSA128DRegs: + break; } - Index = matchACRegisterName(Identifier); - if (Index != -1) { - Parser.Lex(); - Operands.push_back(MipsOperand::CreateACCReg( - Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); + Parser.Lex(); // Eat the '$'. + if (getLexer().getKind() == AsmToken::Identifier) + RegName = Parser.getTok().getString().lower(); + else + return MatchOperand_ParseFail; + + int RegNum = matchMSA128RegisterName(RegName); + + if (RegNum < 0 || RegNum > 31) + return MatchOperand_ParseFail; + + int RegVal = getReg(regKindToRegClass(Kind), RegNum); + if (RegVal == -1) + return MatchOperand_ParseFail; + + MipsOperand *Op = MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc()); + Op->setRegKind(Kind); + Operands.push_back(Op); + + Parser.Lex(); // Eat the register identifier. + + // MSA registers may be suffixed with an index in the form of: + // 1) Immediate expression. + // 2) General Purpose Register. + // Examples: + // 1) copy_s.b $29,$w0[0] + // 2) sld.b $w0,$w1[$1] + + if (Parser.getTok().isNot(AsmToken::LBrac)) return MatchOperand_Success; - } - Index = matchMSA128RegisterName(Identifier); - if (Index != -1) { - Parser.Lex(); - Operands.push_back(MipsOperand::CreateMSA128Reg( - Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); + MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]); + + Operands.push_back(MipsOperand::CreateToken("[", Parser.getTok().getLoc())); + Parser.Lex(); // Parse the '[' token. + + if (Parser.getTok().is(AsmToken::Dollar)) { + // This must be a GPR. + MipsOperand *RegOp; + SMLoc VIdx = Parser.getTok().getLoc(); + Parser.Lex(); // Parse the '$' token. + + // GPR have aliases and we must account for that. Example: $30 == $fp + if (getLexer().getKind() == AsmToken::Integer) { + unsigned RegNum = Parser.getTok().getIntVal(); + int Reg = matchRegisterByNumber( + RegNum, regKindToRegClass(MipsOperand::Kind_GPR32)); + if (Reg == -1) { + Error(VIdx, "invalid general purpose register"); + return MatchOperand_ParseFail; + } + + RegOp = MipsOperand::CreateReg(Reg, VIdx, Parser.getTok().getLoc()); + } else if (getLexer().getKind() == AsmToken::Identifier) { + int RegNum = -1; + std::string RegName = Parser.getTok().getString().lower(); + + RegNum = matchCPURegisterName(RegName); + if (RegNum == -1) { + Error(VIdx, "general purpose register expected"); + return MatchOperand_ParseFail; + } + RegNum = getReg(regKindToRegClass(MipsOperand::Kind_GPR32), RegNum); + RegOp = MipsOperand::CreateReg(RegNum, VIdx, Parser.getTok().getLoc()); + } else + return MatchOperand_ParseFail; + + RegOp->setRegKind(MipsOperand::Kind_GPR32); + Operands.push_back(RegOp); + Parser.Lex(); // Eat the register identifier. + + if (Parser.getTok().isNot(AsmToken::RBrac)) + return MatchOperand_ParseFail; + + Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc())); + Parser.Lex(); // Parse the ']' token. + return MatchOperand_Success; } - Index = matchMSA128CtrlRegisterName(Identifier); - if (Index != -1) { - Parser.Lex(); - Operands.push_back(MipsOperand::CreateMSACtrlReg( - Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); - return MatchOperand_Success; + // The index must be a constant expression then. + SMLoc VIdx = Parser.getTok().getLoc(); + const MCExpr *ImmVal; + + if (getParser().parseExpression(ImmVal)) + return MatchOperand_ParseFail; + + const MCConstantExpr *expr = dyn_cast<MCConstantExpr>(ImmVal); + if (!expr || !validateMSAIndex((int)expr->getValue(), Kind)) { + Error(VIdx, "invalid immediate value"); + return MatchOperand_ParseFail; } - return MatchOperand_NoMatch; + SMLoc E = Parser.getTok().getEndLoc(); + + if (Parser.getTok().isNot(AsmToken::RBrac)) + return MatchOperand_ParseFail; + + bool insve = + Mnemonic->getToken() == "insve.b" || Mnemonic->getToken() == "insve.h" || + Mnemonic->getToken() == "insve.w" || Mnemonic->getToken() == "insve.d"; + + // The second vector index of insve instructions is always 0. + if (insve && Operands.size() > 6) { + if (expr->getValue() != 0) { + Error(VIdx, "immediate value must be 0"); + return MatchOperand_ParseFail; + } + Operands.push_back(MipsOperand::CreateToken("0", VIdx)); + } else + Operands.push_back(MipsOperand::CreateImm(expr, VIdx, E)); + + Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc())); + + Parser.Lex(); // Parse the ']' token. + + return MatchOperand_Success; } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::ParseAnyRegisterWithoutDollar( - SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc S) { - auto Token = Parser.getTok(); - - if (Token.is(AsmToken::Identifier)) { - DEBUG(dbgs() << ".. identifier\n"); - StringRef Identifier = Token.getIdentifier(); - return MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S); - } else if (Token.is(AsmToken::Integer)) { - DEBUG(dbgs() << ".. integer\n"); - Operands.push_back(MipsOperand::CreateNumericReg( - Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(), - *this)); - Parser.Lex(); - return MatchOperand_Success; - } +MipsAsmParser::parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind) { + MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; - DEBUG(dbgs() << Parser.getTok().getKind() << "\n"); + if (Kind != MipsOperand::Kind_MSA128CtrlRegs) + return MatchOperand_NoMatch; - return MatchOperand_NoMatch; + if (Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_ParseFail; + + SMLoc S = Parser.getTok().getLoc(); + + Parser.Lex(); // Eat the '$' symbol. + + int RegNum = -1; + if (getLexer().getKind() == AsmToken::Identifier) + RegNum = matchMSA128CtrlRegisterName(Parser.getTok().getString().lower()); + else if (getLexer().getKind() == AsmToken::Integer) + RegNum = Parser.getTok().getIntVal(); + else + return MatchOperand_ParseFail; + + if (RegNum < 0 || RegNum > 7) + return MatchOperand_ParseFail; + + int RegVal = getReg(regKindToRegClass(Kind), RegNum); + if (RegVal == -1) + return MatchOperand_ParseFail; + + MipsOperand *RegOp = + MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc()); + RegOp->setRegKind(MipsOperand::Kind_MSA128CtrlRegs); + Operands.push_back(RegOp); + Parser.Lex(); // Eat the register identifier. + + return MatchOperand_Success; } -MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister( - SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - DEBUG(dbgs() << "ParseAnyRegister\n"); +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - auto Token = Parser.getTok(); + if (!isGP64()) + return MatchOperand_NoMatch; + return parseRegs(Operands, (int)MipsOperand::Kind_GPR64); +} - SMLoc S = Token.getLoc(); +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_GPR32); +} - if (Token.isNot(AsmToken::Dollar)) { - DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); - if (Token.is(AsmToken::Identifier)) { - if (searchSymbolAlias(Operands)) - return MatchOperand_Success; - } - DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAFGR64Regs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + + if (isFP64()) return MatchOperand_NoMatch; - } - DEBUG(dbgs() << ".. $\n"); - Parser.Lex(); - Token = Parser.getTok(); + return parseRegs(Operands, (int)MipsOperand::Kind_AFGR64Regs); +} - OperandMatchResultTy ResTy = ParseAnyRegisterWithoutDollar(Operands, S); - if (ResTy == MatchOperand_NoMatch) - return MatchOperand_ParseFail; // We ate the $ so NoMatch isn't valid - return ResTy; +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + if (!isFP64()) + return MatchOperand_NoMatch; + return parseRegs(Operands, (int)MipsOperand::Kind_FGR64Regs); } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - switch (getLexer().getKind()) { - default: +MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_FGR32Regs); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseFGRH32Regs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_FGRH32Regs); +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_FCCRegs); +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_ACC64DSP); +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + // If the first token is not '$' we have an error. + if (Parser.getTok().isNot(AsmToken::Dollar)) return MatchOperand_NoMatch; - case AsmToken::LParen: - case AsmToken::Minus: - case AsmToken::Plus: - case AsmToken::Integer: - case AsmToken::String: - break; - } - const MCExpr *IdVal; SMLoc S = Parser.getTok().getLoc(); - if (getParser().parseExpression(IdVal)) - return MatchOperand_ParseFail; + Parser.Lex(); // Eat the '$' - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); + const AsmToken &Tok = Parser.getTok(); // Get next token. + + if (Tok.isNot(AsmToken::Identifier)) + return MatchOperand_NoMatch; + + if (!Tok.getIdentifier().startswith("ac")) + return MatchOperand_NoMatch; + + StringRef NumString = Tok.getIdentifier().substr(2); + + unsigned IntVal; + if (NumString.getAsInteger(10, IntVal)) + return MatchOperand_NoMatch; + + unsigned Reg = matchRegisterByNumber(IntVal, Mips::LO32DSPRegClassID); + + MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); + Op->setRegKind(MipsOperand::Kind_LO32DSP); + Operands.push_back(Op); + + Parser.Lex(); // Eat the register number. return MatchOperand_Success; } -MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget( - SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - DEBUG(dbgs() << "ParseJumpTarget\n"); +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + // If the first token is not '$' we have an error. + if (Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_NoMatch; - SMLoc S = getLexer().getLoc(); + SMLoc S = Parser.getTok().getLoc(); + Parser.Lex(); // Eat the '$' - // Integers and expressions are acceptable - OperandMatchResultTy ResTy = ParseImm(Operands); - if (ResTy != MatchOperand_NoMatch) - return ResTy; + const AsmToken &Tok = Parser.getTok(); // Get next token. - // Consume the $ if there is one. We'll add it to the symbol below. - bool hasConsumedDollar = false; - if (getLexer().is(AsmToken::Dollar)) { - Parser.Lex(); - hasConsumedDollar = true; + if (Tok.isNot(AsmToken::Identifier)) + return MatchOperand_NoMatch; - // We have an unfortunate conflict between '$sym' and '$reg' so give - // registers a chance before we try symbols. - // The conflict is between 'bc1t $offset', and 'bc1t $fcc, $offset'. - OperandMatchResultTy ResTy = ParseAnyRegisterWithoutDollar(Operands, S); - if (ResTy != MatchOperand_NoMatch) - return ResTy; - } + if (!Tok.getIdentifier().startswith("ac")) + return MatchOperand_NoMatch; - StringRef Identifier; - if (Parser.parseIdentifier(Identifier)) - return hasConsumedDollar ? MatchOperand_ParseFail : MatchOperand_NoMatch; + StringRef NumString = Tok.getIdentifier().substr(2); - if (hasConsumedDollar) - Identifier = StringRef("$" + Identifier.str()); + unsigned IntVal; + if (NumString.getAsInteger(10, IntVal)) + return MatchOperand_NoMatch; - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); + unsigned Reg = matchRegisterByNumber(IntVal, Mips::HI32DSPRegClassID); - // Create a symbol reference. - const MCExpr *Res = - MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); + MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); + Op->setRegKind(MipsOperand::Kind_HI32DSP); + Operands.push_back(Op); - Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this)); + Parser.Lex(); // Eat the register number. return MatchOperand_Success; - // // Look for the existing symbol, we should check if - // // we need to assign the proper RegisterKind. - // if (searchSymbolAlias(Operands)) - // return false; +} - return MatchOperand_NoMatch; +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + // If the first token is not '$' we have an error. + if (Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_NoMatch; + + SMLoc S = Parser.getTok().getLoc(); + Parser.Lex(); // Eat the '$' + + const AsmToken &Tok = Parser.getTok(); // Get next token. + + if (Tok.isNot(AsmToken::Integer)) + return MatchOperand_NoMatch; + + unsigned IntVal = Tok.getIntVal(); + + unsigned Reg = matchRegisterByNumber(IntVal, Mips::COP2RegClassID); + + MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); + Op->setRegKind(MipsOperand::Kind_COP2); + Operands.push_back(Op); + + Parser.Lex(); // Eat the register number. + return MatchOperand_Success; +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128BRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128BRegs); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128HRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128HRegs); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128WRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128WRegs); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128DRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128DRegs); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128CtrlRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSACtrlRegs(Operands, (int)MipsOperand::Kind_MSA128CtrlRegs); +} + +bool MipsAsmParser::searchSymbolAlias( + SmallVectorImpl<MCParsedAsmOperand *> &Operands, unsigned RegKind) { + + MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier()); + if (Sym) { + SMLoc S = Parser.getTok().getLoc(); + const MCExpr *Expr; + if (Sym->isVariable()) + Expr = Sym->getVariableValue(); + else + return false; + if (Expr->getKind() == MCExpr::SymbolRef) { + MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; + const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); + const StringRef DefSymbol = Ref->getSymbol().getName(); + if (DefSymbol.startswith("$")) { + int RegNum = -1; + APInt IntVal(32, -1); + if (!DefSymbol.substr(1).getAsInteger(10, IntVal)) + RegNum = matchRegisterByNumber(IntVal.getZExtValue(), + isGP64() ? Mips::GPR64RegClassID + : Mips::GPR32RegClassID); + else { + // Lookup for the register with the corresponding name. + switch (Kind) { + case MipsOperand::Kind_AFGR64Regs: + case MipsOperand::Kind_FGR64Regs: + RegNum = matchFPURegisterName(DefSymbol.substr(1)); + break; + case MipsOperand::Kind_FGR32Regs: + RegNum = matchFPURegisterName(DefSymbol.substr(1)); + break; + case MipsOperand::Kind_GPR64: + case MipsOperand::Kind_GPR32: + default: + RegNum = matchCPURegisterName(DefSymbol.substr(1)); + break; + } + if (RegNum > -1) + RegNum = getReg(regKindToRegClass(Kind), RegNum); + } + if (RegNum > -1) { + Parser.Lex(); + MipsOperand *op = + MipsOperand::CreateReg(RegNum, S, Parser.getTok().getLoc()); + op->setRegKind(Kind); + Operands.push_back(op); + return true; + } + } + } else if (Expr->getKind() == MCExpr::Constant) { + Parser.Lex(); + const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr); + MipsOperand *op = + MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc()); + Operands.push_back(op); + return true; + } + } + return false; +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_HWRegs); +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_CCRRegs); } MipsAsmParser::OperandMatchResultTy @@ -1919,12 +2215,12 @@ MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { int64_t Val = MCE->getValue(); SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); Operands.push_back(MipsOperand::CreateImm( - MCConstantExpr::Create(0 - Val, getContext()), S, E, *this)); + MCConstantExpr::Create(0 - Val, getContext()), S, E)); return MatchOperand_Success; } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { +MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { switch (getLexer().getKind()) { default: return MatchOperand_NoMatch; @@ -1958,7 +2254,7 @@ MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { } Operands.push_back( - MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this)); + MipsOperand::CreateLSAImm(Expr, S, Parser.getTok().getLoc())); return MatchOperand_Success; } @@ -1996,74 +2292,16 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { return VK; } -/// Sometimes (i.e. load/stores) the operand may be followed immediately by -/// either this. -/// ::= '(', register, ')' -/// handle it before we iterate so we don't get tripped up by the lack of -/// a comma. -bool MipsAsmParser::ParseParenSuffix( - StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - if (getLexer().is(AsmToken::LParen)) { - Operands.push_back( - MipsOperand::CreateToken("(", getLexer().getLoc(), *this)); - Parser.Lex(); - if (ParseOperand(Operands, Name)) { - SMLoc Loc = getLexer().getLoc(); - Parser.eatToEndOfStatement(); - return Error(Loc, "unexpected token in argument list"); - } - if (Parser.getTok().isNot(AsmToken::RParen)) { - SMLoc Loc = getLexer().getLoc(); - Parser.eatToEndOfStatement(); - return Error(Loc, "unexpected token, expected ')'"); - } - Operands.push_back( - MipsOperand::CreateToken(")", getLexer().getLoc(), *this)); - Parser.Lex(); - } - return false; -} - -/// Sometimes (i.e. in MSA) the operand may be followed immediately by -/// either one of these. -/// ::= '[', register, ']' -/// ::= '[', integer, ']' -/// handle it before we iterate so we don't get tripped up by the lack of -/// a comma. -bool MipsAsmParser::ParseBracketSuffix( - StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - if (getLexer().is(AsmToken::LBrac)) { - Operands.push_back( - MipsOperand::CreateToken("[", getLexer().getLoc(), *this)); - Parser.Lex(); - if (ParseOperand(Operands, Name)) { - SMLoc Loc = getLexer().getLoc(); - Parser.eatToEndOfStatement(); - return Error(Loc, "unexpected token in argument list"); - } - if (Parser.getTok().isNot(AsmToken::RBrac)) { - SMLoc Loc = getLexer().getLoc(); - Parser.eatToEndOfStatement(); - return Error(Loc, "unexpected token, expected ']'"); - } - Operands.push_back( - MipsOperand::CreateToken("]", getLexer().getLoc(), *this)); - Parser.Lex(); - } - return false; -} - bool MipsAsmParser::ParseInstruction( ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand *> &Operands) { - DEBUG(dbgs() << "ParseInstruction\n"); // Check if we have valid mnemonic if (!mnemonicIsValid(Name, 0)) { Parser.eatToEndOfStatement(); return Error(NameLoc, "Unknown instruction"); } // First operand in MCInst is instruction mnemonic. - Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this)); + Operands.push_back(MipsOperand::CreateToken(Name, NameLoc)); // Read the remaining operands. if (getLexer().isNot(AsmToken::EndOfStatement)) { @@ -2073,9 +2311,6 @@ bool MipsAsmParser::ParseInstruction( Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); } - if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands)) - return true; - // AFAIK, parenthesis suffixes are never on the first operand while (getLexer().is(AsmToken::Comma)) { Parser.Lex(); // Eat the comma. @@ -2085,13 +2320,6 @@ bool MipsAsmParser::ParseInstruction( Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); } - // Parse bracket and parenthesis suffixes before we iterate - if (getLexer().is(AsmToken::LBrac)) { - if (ParseBracketSuffix(Name, Operands)) - return true; - } else if (getLexer().is(AsmToken::LParen) && - ParseParenSuffix(Name, Operands)) - return true; } } if (getLexer().isNot(AsmToken::EndOfStatement)) { |