diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 2b80d3f03de..95e7d09ce0c 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -23,6 +23,7 @@ #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" @@ -57,7 +58,6 @@ private: namespace { class MipsAsmParser : public MCTargetAsmParser { - MipsTargetStreamer &getTargetStreamer() { MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer(); return static_cast(TS); @@ -66,7 +66,6 @@ class MipsAsmParser : public MCTargetAsmParser { MCSubtargetInfo &STI; MCAsmParser &Parser; MipsAssemblerOptions Options; - bool hasConsumedDollar; #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" @@ -76,104 +75,52 @@ 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 &Operands); + + bool ParseBracketSuffix(StringRef Name, + SmallVectorImpl &Operands); + bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, SmallVectorImpl &Operands); bool ParseDirective(AsmToken DirectiveID); - MipsAsmParser::OperandMatchResultTy - parseRegs(SmallVectorImpl &Operands, int RegKind); - - MipsAsmParser::OperandMatchResultTy - parseMSARegs(SmallVectorImpl &Operands, int RegKind); - - MipsAsmParser::OperandMatchResultTy - parseMSACtrlRegs(SmallVectorImpl &Operands, - int RegKind); - MipsAsmParser::OperandMatchResultTy parseMemOperand(SmallVectorImpl &Operands); - bool parsePtrReg(SmallVectorImpl &Operands, - int RegKind); + MipsAsmParser::OperandMatchResultTy MatchAnyRegisterNameWithoutDollar( + SmallVectorImpl &Operands, StringRef Identifier, + SMLoc S); MipsAsmParser::OperandMatchResultTy - parsePtrReg(SmallVectorImpl &Operands); + ParseAnyRegisterWithoutDollar(SmallVectorImpl &Operands, + SMLoc S); MipsAsmParser::OperandMatchResultTy - parseGPR32(SmallVectorImpl &Operands); + ParseAnyRegister(SmallVectorImpl &Operands); MipsAsmParser::OperandMatchResultTy - parseGPR64(SmallVectorImpl &Operands); + ParseImm(SmallVectorImpl &Operands); MipsAsmParser::OperandMatchResultTy - parseHWRegs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseCCRRegs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseAFGR64Regs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseFGR64Regs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseFGR32Regs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseFGRH32Regs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseFCCRegs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseACC64DSP(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseLO32DSP(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseHI32DSP(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseCOP2(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseMSA128BRegs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseMSA128HRegs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseMSA128WRegs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseMSA128DRegs(SmallVectorImpl &Operands); - - MipsAsmParser::OperandMatchResultTy - parseMSA128CtrlRegs(SmallVectorImpl &Operands); + ParseJumpTarget(SmallVectorImpl &Operands); MipsAsmParser::OperandMatchResultTy parseInvNum(SmallVectorImpl &Operands); MipsAsmParser::OperandMatchResultTy - parseLSAImm(SmallVectorImpl &Operands); + ParseLSAImm(SmallVectorImpl &Operands); - bool searchSymbolAlias(SmallVectorImpl &Operands, - unsigned RegKind); + bool searchSymbolAlias(SmallVectorImpl &Operands); bool ParseOperand(SmallVectorImpl &, StringRef Mnemonic); - int tryParseRegister(bool is64BitReg); - - bool tryParseRegisterOperand(SmallVectorImpl &Operands, - bool is64BitReg); - bool needsExpansion(MCInst &Inst); void expandInstruction(MCInst &Inst, SMLoc IDLoc, @@ -235,8 +182,6 @@ class MipsAsmParser : public MCTargetAsmParser { bool eatComma(StringRef ErrorStr); - int matchRegisterName(StringRef Symbol, bool is64BitReg); - int matchCPURegisterName(StringRef Symbol); int matchRegisterByNumber(unsigned RegNum, unsigned RegClass); @@ -251,17 +196,12 @@ 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 &Instructions); @@ -287,8 +227,7 @@ class MipsAsmParser : public MCTargetAsmParser { public: MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII) - : MCTargetAsmParser(), STI(sti), Parser(parser), - hasConsumedDollar(false) { + : MCTargetAsmParser(), STI(sti), Parser(parser) { // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); @@ -301,6 +240,9 @@ 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); }; } @@ -309,53 +251,56 @@ namespace { /// MipsOperand - Instances of this class represent a parsed Mips machine /// instruction. class MipsOperand : public MCParsedAsmOperand { - public: - 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 + /// 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 }; private: enum KindTy { - k_CondCode, - k_CoprocNum, k_Immediate, k_Memory, - k_PostIndexRegister, - k_Register, - k_PtrReg, - k_Token, - k_LSAImm + k_PhysRegister, + k_RegisterIndex, + k_Token } Kind; - MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} + MipsOperand(KindTy K, MipsAsmParser &Parser) + : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {} + + /// For diagnostics, and checking the assembler temporary + MipsAsmParser &AsmParser; struct Token { const char *Data; unsigned Length; }; - struct RegOp { - unsigned RegNum; - RegisterKind Kind; + 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 ImmOp { @@ -363,30 +308,161 @@ private: }; struct MemOp { - unsigned Base; + MipsOperand *Base; const MCExpr *Off; }; union { struct Token Tok; - struct RegOp Reg; + struct PhysRegOp PhysReg; + struct RegIdxOp RegIdx; 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: - void addRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getReg())); + /// 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); } - void addPtrRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getPtrReg())); + /// 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); } +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); + } + +public: void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediate when possible. Null MCExpr = 0. if (Expr == 0) @@ -397,6 +473,85 @@ 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(); @@ -406,19 +561,38 @@ public: void addMemOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getMemBase())); + Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg())); const MCExpr *Expr = getMemOff(); addExpr(Inst, Expr); } - bool isReg() const { return Kind == k_Register; } + 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 isImm() const { return Kind == k_Immediate; } - bool isToken() const { return Kind == k_Token; } + bool isConstantImm() const { + return isImm() && dyn_cast(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 isMem() const { return Kind == k_Memory; } - bool isPtrReg() const { return Kind == k_PtrReg; } bool isInvNum() const { return Kind == k_Immediate; } - bool isLSAImm() const { return Kind == k_LSAImm; } + bool isLSAImm() const { + if (!isConstantImm()) + return false; + int64_t Val = getConstantImm(); + return 1 <= Val && Val <= 4; + } StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); @@ -426,26 +600,27 @@ public: } unsigned getReg() const { - assert((Kind == k_Register) && "Invalid access!"); - return Reg.RegNum; - } + // 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 - unsigned getPtrReg() const { - assert((Kind == k_PtrReg) && "Invalid access!"); - return Reg.RegNum; - } - - void setRegKind(RegisterKind RegKind) { - assert((Kind == k_Register || Kind == k_PtrReg) && "Invalid access!"); - Reg.Kind = RegKind; + assert(Kind == k_PhysRegister && "Invalid access!"); + return PhysReg.Num; } const MCExpr *getImm() const { - assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!"); + assert((Kind == k_Immediate) && "Invalid access!"); return Imm.Val; } - unsigned getMemBase() const { + int64_t getConstantImm() const { + const MCExpr *Val = getImm(); + return static_cast(Val)->getValue(); + } + + MipsOperand *getMemBase() const { assert((Kind == k_Memory) && "Invalid access!"); return Mem.Base; } @@ -455,8 +630,9 @@ public: return Mem.Off; } - static MipsOperand *CreateToken(StringRef Str, SMLoc S) { - MipsOperand *Op = new MipsOperand(k_Token); + static MipsOperand *CreateToken(StringRef Str, SMLoc S, + MipsAsmParser &Parser) { + MipsOperand *Op = new MipsOperand(k_Token, Parser); Op->Tok.Data = Str.data(); Op->Tok.Length = Str.size(); Op->StartLoc = S; @@ -464,43 +640,75 @@ public: return Op; } - 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 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); } - 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 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); } - static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { - MipsOperand *Op = new MipsOperand(k_Immediate); + /// 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); + } + + /// 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); + } + + /// 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, + MipsAsmParser &Parser) { + MipsOperand *Op = new MipsOperand(k_Immediate, Parser); Op->Imm.Val = Val; Op->StartLoc = S; Op->EndLoc = E; return Op; } - 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(unsigned Base, const MCExpr *Off, SMLoc S, - SMLoc E) { - MipsOperand *Op = new MipsOperand(k_Memory); + static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S, + SMLoc E, MipsAsmParser &Parser) { + MipsOperand *Op = new MipsOperand(k_Memory, Parser); Op->Mem.Base = Base; Op->Mem.Off = Off; Op->StartLoc = S; @@ -508,79 +716,33 @@ public: return Op; } - bool isGPR32Asm() const { - return Kind == k_Register && Reg.Kind == Kind_GPR32; + bool isGPRAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; } - void addRegAsmOperands(MCInst &Inst, unsigned N) const { - Inst.addOperand(MCOperand::CreateReg(Reg.RegNum)); + bool isFGRAsmReg() const { + // AFGR64 is $0-$15 but we handle this in getAFGR64() + return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; } - - bool isGPR64Asm() const { - return Kind == k_Register && Reg.Kind == Kind_GPR64; + bool isHWRegsAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31; } - - bool isHWRegsAsm() const { - assert((Kind == k_Register) && "Invalid access!"); - return Reg.Kind == Kind_HWRegs; + bool isCCRAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31; } - - bool isCCRAsm() const { - assert((Kind == k_Register) && "Invalid access!"); - return Reg.Kind == Kind_CCRRegs; + bool isFCCAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7; } - - bool isAFGR64Asm() const { - return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs; + bool isACCAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3; } - - bool isFGR64Asm() const { - return Kind == k_Register && Reg.Kind == Kind_FGR64Regs; + bool isCOP2AsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31; } - - bool isFGR32Asm() const { - return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs; + bool isMSA128AsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31; } - - bool isFGRH32Asm() const { - return (Kind == k_Register) && Reg.Kind == Kind_FGRH32Regs; - } - - bool isFCCRegsAsm() const { - return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs; - } - - 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; + bool isMSACtrlAsmReg() const { + return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7; } /// getStartLoc - Get the location of the first token of this operand. @@ -589,7 +751,29 @@ public: SMLoc getEndLoc() const { return EndLoc; } virtual void print(raw_ostream &OS) const { - llvm_unreachable("unimplemented!"); + 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; + } } }; // class MipsOperand } // namespace @@ -616,6 +800,8 @@ 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()) @@ -633,6 +819,14 @@ 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()) @@ -996,14 +1190,13 @@ bool MipsAsmParser::MatchAndEmitInstruction( return true; } -void MipsAsmParser::warnIfAssemblerTemporary(int RegNo) { - if ((RegNo != 0) && ((int)Options.getATRegNum() == RegNo)) { - if (RegNo == 1) - Warning(getLexer().getLoc(), "Used $at without \".set noat\""); +void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) { + if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) { + if (RegIndex == 1) + Warning(Loc, "Used $at without \".set noat\""); else - Warning(getLexer().getLoc(), Twine("Used $") + Twine(RegNo) + - " with \".set at=$" + Twine(RegNo) + - "\""); + Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" + + Twine(RegIndex) + "\""); } } @@ -1064,8 +1257,6 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) { .Default(-1); } - warnIfAssemblerTemporary(CC); - return CC; } @@ -1140,59 +1331,6 @@ 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; @@ -1222,45 +1360,14 @@ 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(Tok.getIntVal()), - is64BitReg ? Mips::GPR64RegClassID - : Mips::GPR32RegClassID); - return RegNum; -} - -bool MipsAsmParser::tryParseRegisterOperand( - SmallVectorImpl &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 &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); @@ -1272,6 +1379,8 @@ MipsAsmParser::ParseOperand(SmallVectorImpl &Operands, if (ResTy == MatchOperand_ParseFail) return true; + DEBUG(dbgs() << ".. Generic Parser\n"); + switch (getLexer().getKind()) { default: Error(Parser.getTok().getLoc(), "unexpected token in operand"); @@ -1279,29 +1388,15 @@ MipsAsmParser::ParseOperand(SmallVectorImpl &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; - 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(); - } + // 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; - } + // Maybe it is a symbol reference. StringRef Identifier; if (Parser.parseIdentifier(Identifier)) @@ -1313,47 +1408,18 @@ MipsAsmParser::ParseOperand(SmallVectorImpl &Operands, const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); - Operands.push_back(MipsOperand::CreateImm(Res, S, E)); + Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this)); 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: { - // 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; + DEBUG(dbgs() << ".. generic integer\n"); + OperandMatchResultTy ResTy = ParseImm(Operands); + return ResTy != MatchOperand_Success; } case AsmToken::Percent: { // It is a symbol reference or constant expression. @@ -1364,7 +1430,7 @@ MipsAsmParser::ParseOperand(SmallVectorImpl &Operands, SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); + Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); return false; } // case AsmToken::Percent } // switch(getLexer().getKind()) @@ -1496,9 +1562,27 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { - StartLoc = Parser.getTok().getLoc(); - RegNo = tryParseRegister(isGP64()); - EndLoc = Parser.getTok().getLoc(); + SmallVector Operands; + OperandMatchResultTy ResTy = ParseAnyRegister(Operands); + if (ResTy == MatchOperand_Success) { + assert(Operands.size() == 1); + MipsOperand &Operand = *static_cast(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); return (RegNo == (unsigned)-1); } @@ -1532,7 +1616,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( SmallVectorImpl &Operands) { - + DEBUG(dbgs() << "parseMemOperand\n"); const MCExpr *IdVal = 0; SMLoc S; bool isParenExpr = false; @@ -1555,7 +1639,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)); + Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); return MatchOperand_Success; } if (Tok.is(AsmToken::EndOfStatement)) { @@ -1563,8 +1647,9 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); // Zero register assumed, add a memory operand with ZERO as its base. - Operands.push_back(MipsOperand::CreateMem( - isGP64() ? Mips::ZERO_64 : Mips::ZERO, IdVal, S, E)); + MipsOperand *Base = MipsOperand::CreateGPRReg( + 0, getContext().getRegisterInfo(), S, E, *this); + Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this)); return MatchOperand_Success; } Error(Parser.getTok().getLoc(), "'(' expected"); @@ -1574,8 +1659,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( Parser.Lex(); // Eat the '(' token. } - Res = parseRegs(Operands, isGP64() ? (int)MipsOperand::Kind_GPR64 - : (int)MipsOperand::Kind_GPR32); + Res = ParseAnyRegister(Operands); if (Res != MatchOperand_Success) return Res; @@ -1593,7 +1677,6 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( // Replace the register operand with the memory operand. MipsOperand *op = static_cast(Operands.back()); - int RegNo = op->getReg(); // Remove the register from the operands. Operands.pop_back(); // Add the memory operand. @@ -1606,531 +1689,12 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( getContext()); } - Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E)); - delete op; + Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this)); return MatchOperand_Success; } -bool MipsAsmParser::parsePtrReg(SmallVectorImpl &Operands, - int RegKind) { - // If the first token is not '$' we have an error. - if (Parser.getTok().isNot(AsmToken::Dollar)) - return false; - - 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; - } else if (TkKind == AsmToken::Identifier) { - if ((Reg = matchCPURegisterName(Parser.getTok().getString().lower())) == -1) - return false; - Reg = getReg(regKindToRegClass(RegKind), Reg); - } else { - 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::parsePtrReg(SmallVectorImpl &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 &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; -} - -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; - } -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseMSARegs(SmallVectorImpl &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; - } - - 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; - - MipsOperand *Mnemonic = static_cast(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; - } - - // 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(ImmVal); - if (!expr || !validateMSAIndex((int)expr->getValue(), Kind)) { - Error(VIdx, "invalid immediate value"); - return MatchOperand_ParseFail; - } - - 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::parseMSACtrlRegs(SmallVectorImpl &Operands, - int RegKind) { - MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; - - if (Kind != MipsOperand::Kind_MSA128CtrlRegs) - 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::parseGPR64(SmallVectorImpl &Operands) { - - if (!isGP64()) - return MatchOperand_NoMatch; - return parseRegs(Operands, (int)MipsOperand::Kind_GPR64); -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseGPR32(SmallVectorImpl &Operands) { - return parseRegs(Operands, (int)MipsOperand::Kind_GPR32); -} - -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAFGR64Regs( - SmallVectorImpl &Operands) { - - if (isFP64()) - return MatchOperand_NoMatch; - return parseRegs(Operands, (int)MipsOperand::Kind_AFGR64Regs); -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseFGR64Regs(SmallVectorImpl &Operands) { - if (!isFP64()) - return MatchOperand_NoMatch; - return parseRegs(Operands, (int)MipsOperand::Kind_FGR64Regs); -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseFGR32Regs(SmallVectorImpl &Operands) { - return parseRegs(Operands, (int)MipsOperand::Kind_FGR32Regs); -} - -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseFGRH32Regs( - SmallVectorImpl &Operands) { - return parseRegs(Operands, (int)MipsOperand::Kind_FGRH32Regs); -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseFCCRegs(SmallVectorImpl &Operands) { - return parseRegs(Operands, (int)MipsOperand::Kind_FCCRegs); -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseACC64DSP(SmallVectorImpl &Operands) { - return parseRegs(Operands, (int)MipsOperand::Kind_ACC64DSP); -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseLO32DSP(SmallVectorImpl &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::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::parseHI32DSP(SmallVectorImpl &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::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::HI32DSPRegClassID); - - MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); - Op->setRegKind(MipsOperand::Kind_HI32DSP); - Operands.push_back(Op); - - Parser.Lex(); // Eat the register number. - return MatchOperand_Success; -} - -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseCOP2(SmallVectorImpl &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 &Operands) { - return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128BRegs); -} - -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128HRegs( - SmallVectorImpl &Operands) { - return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128HRegs); -} - -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128WRegs( - SmallVectorImpl &Operands) { - return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128WRegs); -} - -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128DRegs( - SmallVectorImpl &Operands) { - return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128DRegs); -} - -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128CtrlRegs( - SmallVectorImpl &Operands) { - return parseMSACtrlRegs(Operands, (int)MipsOperand::Kind_MSA128CtrlRegs); -} - bool MipsAsmParser::searchSymbolAlias( - SmallVectorImpl &Operands, unsigned RegKind) { + SmallVectorImpl &Operands) { MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier()); if (Sym) { @@ -2141,49 +1705,22 @@ bool MipsAsmParser::searchSymbolAlias( else return false; if (Expr->getKind() == MCExpr::SymbolRef) { - MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; const MCSymbolRefExpr *Ref = static_cast(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); + 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(Expr); MipsOperand *op = - MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc()); + MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this); Operands.push_back(op); return true; } @@ -2192,13 +1729,180 @@ bool MipsAsmParser::searchSymbolAlias( } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseHWRegs(SmallVectorImpl &Operands) { - return parseRegs(Operands, (int)MipsOperand::Kind_HWRegs); +MipsAsmParser::MatchAnyRegisterNameWithoutDollar( + SmallVectorImpl &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)); + return MatchOperand_Success; + } + + Index = matchFPURegisterName(Identifier); + if (Index != -1) { + Parser.Lex(); + Operands.push_back(MipsOperand::CreateFGRReg( + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); + return MatchOperand_Success; + } + + Index = matchFCCRegisterName(Identifier); + if (Index != -1) { + Parser.Lex(); + Operands.push_back(MipsOperand::CreateFCCReg( + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); + return MatchOperand_Success; + } + + Index = matchACRegisterName(Identifier); + if (Index != -1) { + Parser.Lex(); + Operands.push_back(MipsOperand::CreateACCReg( + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); + return MatchOperand_Success; + } + + Index = matchMSA128RegisterName(Identifier); + if (Index != -1) { + Parser.Lex(); + Operands.push_back(MipsOperand::CreateMSA128Reg( + Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this)); + 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; + } + + return MatchOperand_NoMatch; } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseCCRRegs(SmallVectorImpl &Operands) { - return parseRegs(Operands, (int)MipsOperand::Kind_CCRRegs); +MipsAsmParser::ParseAnyRegisterWithoutDollar( + SmallVectorImpl &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; + } + + DEBUG(dbgs() << Parser.getTok().getKind() << "\n"); + + return MatchOperand_NoMatch; +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister( + SmallVectorImpl &Operands) { + DEBUG(dbgs() << "ParseAnyRegister\n"); + + auto Token = Parser.getTok(); + + SMLoc S = Token.getLoc(); + + 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"); + return MatchOperand_NoMatch; + } + DEBUG(dbgs() << ".. $\n"); + Parser.Lex(); + Token = Parser.getTok(); + + 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::ParseImm(SmallVectorImpl &Operands) { + switch (getLexer().getKind()) { + default: + 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; + + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); + return MatchOperand_Success; +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget( + SmallVectorImpl &Operands) { + DEBUG(dbgs() << "ParseJumpTarget\n"); + + SMLoc S = getLexer().getLoc(); + + // Integers and expressions are acceptable + OperandMatchResultTy ResTy = ParseImm(Operands); + if (ResTy != MatchOperand_NoMatch) + return ResTy; + + // 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; + + // 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; + } + + StringRef Identifier; + if (Parser.parseIdentifier(Identifier)) + return hasConsumedDollar ? MatchOperand_ParseFail : MatchOperand_NoMatch; + + if (hasConsumedDollar) + Identifier = StringRef("$" + Identifier.str()); + + 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, *this)); + 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 @@ -2215,12 +1919,12 @@ MipsAsmParser::parseInvNum(SmallVectorImpl &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)); + MCConstantExpr::Create(0 - Val, getContext()), S, E, *this)); return MatchOperand_Success; } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseLSAImm(SmallVectorImpl &Operands) { +MipsAsmParser::ParseLSAImm(SmallVectorImpl &Operands) { switch (getLexer().getKind()) { default: return MatchOperand_NoMatch; @@ -2254,7 +1958,7 @@ MipsAsmParser::parseLSAImm(SmallVectorImpl &Operands) { } Operands.push_back( - MipsOperand::CreateLSAImm(Expr, S, Parser.getTok().getLoc())); + MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this)); return MatchOperand_Success; } @@ -2292,16 +1996,74 @@ 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 &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 &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 &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)); + Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this)); // Read the remaining operands. if (getLexer().isNot(AsmToken::EndOfStatement)) { @@ -2311,6 +2073,9 @@ 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. @@ -2320,6 +2085,13 @@ 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)) { diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index a5438401323..fc3b922602c 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -263,6 +263,11 @@ static DecodeStatus DecodeExtSize(MCInst &Inst, uint64_t Address, const void *Decoder); +/// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't +/// handle. +template +static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder); namespace llvm { extern Target TheMipselTarget, TheMipsTarget, TheMips64Target, TheMips64elTarget; @@ -304,9 +309,54 @@ extern "C" void LLVMInitializeMipsDisassembler() { createMips64elDisassembler); } - #include "MipsGenDisassemblerTables.inc" +template +static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder) { + typedef DecodeStatus (*DecodeFN)(MCInst &, unsigned, uint64_t, const void *); + // The size of the n field depends on the element size + // The register class also depends on this. + InsnType tmp = fieldFromInstruction(insn, 17, 5); + unsigned NSize = 0; + DecodeFN RegDecoder = nullptr; + if ((tmp & 0x18) == 0x00) { // INSVE_B + NSize = 4; + RegDecoder = DecodeMSA128BRegisterClass; + } else if ((tmp & 0x1c) == 0x10) { // INSVE_H + NSize = 3; + RegDecoder = DecodeMSA128HRegisterClass; + } else if ((tmp & 0x1e) == 0x18) { // INSVE_W + NSize = 2; + RegDecoder = DecodeMSA128WRegisterClass; + } else if ((tmp & 0x1f) == 0x1c) { // INSVE_D + NSize = 1; + RegDecoder = DecodeMSA128DRegisterClass; + } else + llvm_unreachable("Invalid encoding"); + + assert(NSize != 0 && RegDecoder != nullptr); + + // $wd + tmp = fieldFromInstruction(insn, 6, 5); + if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) + return MCDisassembler::Fail; + // $wd_in + if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) + return MCDisassembler::Fail; + // $n + tmp = fieldFromInstruction(insn, 16, NSize); + MI.addOperand(MCOperand::CreateImm(tmp)); + // $ws + tmp = fieldFromInstruction(insn, 11, 5); + if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) + return MCDisassembler::Fail; + // $n2 + MI.addOperand(MCOperand::CreateImm(0)); + + return MCDisassembler::Success; +} + /// readInstruction - read four bytes from the MemoryObject /// and return 32 bit word sorted according to the given endianess static DecodeStatus readInstruction32(const MemoryObject ®ion, diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 04520b7a221..abf36daab41 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -197,6 +197,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::ILVR: return "MipsISD::ILVR"; case MipsISD::PCKEV: return "MipsISD::PCKEV"; case MipsISD::PCKOD: return "MipsISD::PCKOD"; + case MipsISD::INSVE: return "MipsISD::INSVE"; default: return NULL; } } diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 5a105ffc893..35dd39617fb 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -184,6 +184,9 @@ namespace llvm { PCKEV, // Pack even elements PCKOD, // Pack odd elements + // Vector Lane Copy + INSVE, // Copy element from one vector to another + // Combined (XOR (OR $a, $b), -1) VNOR, diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index af4fa6410c8..71d0a18d48c 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -236,17 +236,27 @@ include "MipsInstrFormats.td" // Mips Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// +def MipsJumpTargetAsmOperand : AsmOperandClass { + let Name = "JumpTarget"; + let ParserMethod = "ParseJumpTarget"; + let PredicateMethod = "isImm"; + let RenderMethod = "addImmOperands"; +} + // Instruction operand types def jmptarget : Operand { let EncoderMethod = "getJumpTargetOpValue"; + let ParserMatchClass = MipsJumpTargetAsmOperand; } def brtarget : Operand { let EncoderMethod = "getBranchTargetOpValue"; let OperandType = "OPERAND_PCREL"; let DecoderMethod = "DecodeBranchTarget"; + let ParserMatchClass = MipsJumpTargetAsmOperand; } def calltarget : Operand { let EncoderMethod = "getJumpTargetOpValue"; + let ParserMatchClass = MipsJumpTargetAsmOperand; } def simm10 : Operand; @@ -268,6 +278,11 @@ def simm16_64 : Operand { let DecoderMethod = "DecodeSimm16"; } +// Zero +def uimmz : Operand { + let PrintMethod = "printUnsignedImm"; +} + // Unsigned Operand def uimm5 : Operand { let PrintMethod = "printUnsignedImm"; @@ -295,12 +310,6 @@ def MipsInvertedImmoperand : AsmOperandClass { let ParserMethod = "parseInvNum"; } -def PtrRegAsmOperand : AsmOperandClass { - let Name = "PtrReg"; - let ParserMethod = "parsePtrReg"; -} - - def InvertedImOperand : Operand { let ParserMatchClass = MipsInvertedImmoperand; } @@ -332,7 +341,7 @@ def mem_ea : Operand { def PtrRC : Operand { let MIOperandInfo = (ops ptr_rc); let DecoderMethod = "DecodePtrRegisterClass"; - let ParserMatchClass = PtrRegAsmOperand; + let ParserMatchClass = GPR32AsmOperand; } // size operand of ext instruction @@ -360,6 +369,9 @@ def HI16 : SDNodeXFormgetSExtValue() + 1); }]>; +// Node immediate is zero (e.g. insve.d) +def immz : PatLeaf<(imm), [{ return N->getSExtValue() == 0; }]>; + // Node immediate fits as 16-bit sign extended on target immediate. // e.g. addi, andi def immSExt8 : PatLeaf<(imm), [{ return isInt<8>(N->getSExtValue()); }]>; diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td index 4a30d5ae969..5722c6cf00b 100644 --- a/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/lib/Target/Mips/MipsMSAInstrInfo.td @@ -27,6 +27,9 @@ def SDT_SHF : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>, SDTCisVT<1, i32>, SDTCisSameAs<0, 2>]>; def SDT_ILV : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>]>; +def SDT_INSVE : SDTypeProfile<1, 4, [SDTCisVec<0>, SDTCisSameAs<0, 1>, + SDTCisVT<2, i32>, SDTCisSameAs<0, 3>, + SDTCisVT<4, i32>]>; def MipsVAllNonZero : SDNode<"MipsISD::VALL_NONZERO", SDT_MipsVecCond>; def MipsVAnyNonZero : SDNode<"MipsISD::VANY_NONZERO", SDT_MipsVecCond>; @@ -50,6 +53,7 @@ def MipsILVL : SDNode<"MipsISD::ILVL", SDT_ILV>; def MipsILVR : SDNode<"MipsISD::ILVR", SDT_ILV>; def MipsPCKEV : SDNode<"MipsISD::PCKEV", SDT_ILV>; def MipsPCKOD : SDNode<"MipsISD::PCKOD", SDT_ILV>; +def MipsINSVE : SDNode<"MipsISD::INSVE", SDT_INSVE>; def vsetcc : SDNode<"ISD::SETCC", SDT_VSetCC>; def vfsetcc : SDNode<"ISD::SETCC", SDT_VFSetCC>; @@ -69,7 +73,7 @@ def uimm2 : Operand { // as the encoded value should be subtracted by one. def uimm2LSAAsmOperand : AsmOperandClass { let Name = "LSAImm"; - let ParserMethod = "parseLSAImm"; + let ParserMethod = "ParseLSAImm"; let RenderMethod = "addImmOperands"; } @@ -156,6 +160,15 @@ def vinsert_v4i32 : PatFrag<(ops node:$vec, node:$val, node:$idx), def vinsert_v2i64 : PatFrag<(ops node:$vec, node:$val, node:$idx), (v2i64 (vector_insert node:$vec, node:$val, node:$idx))>; +def insve_v16i8 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2), + (v16i8 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>; +def insve_v8i16 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2), + (v8i16 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>; +def insve_v4i32 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2), + (v4i32 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>; +def insve_v2i64 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2), + (v2i64 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>; + class vfsetcc_type : PatFrag<(ops node:$lhs, node:$rhs), (ResTy (vfsetcc (OpTy node:$lhs), (OpTy node:$rhs), CC))>; @@ -1402,9 +1415,9 @@ class MSA_3R_SPLAT_DESC_BASE { dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, GPR32:$rt); + dag InOperandList = (ins ROWS:$ws, GPR32Opnd:$rt); string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$rt]"); - list Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, GPR32:$rt))]; + list Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, GPR32Opnd:$rt))]; InstrItinClass Itinerary = itin; } @@ -1425,10 +1438,10 @@ class MSA_3R_SLD_DESC_BASE { dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, GPR32:$rt); + dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, GPR32Opnd:$rt); string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$rt]"); list Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROWS:$ws, - GPR32:$rt))]; + GPR32Opnd:$rt))]; InstrItinClass Itinerary = itin; string Constraints = "$wd = $wd_in"; } @@ -1496,11 +1509,12 @@ class MSA_INSVE_DESC_BASE { dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, uimm6:$n, ROWS:$ws); - string AsmString = !strconcat(instr_asm, "\t$wd[$n], $ws[0]"); + dag InOperandList = (ins ROWD:$wd_in, uimm6:$n, ROWS:$ws, uimmz:$n2); + string AsmString = !strconcat(instr_asm, "\t$wd[$n], $ws[$n2]"); list Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, immZExt6:$n, - ROWS:$ws))]; + ROWS:$ws, + immz:$n2))]; InstrItinClass Itinerary = itin; string Constraints = "$wd = $wd_in"; } @@ -2291,13 +2305,13 @@ class INSERT_FW_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE; -class INSVE_B_DESC : MSA_INSVE_DESC_BASE<"insve.b", int_mips_insve_b, +class INSVE_B_DESC : MSA_INSVE_DESC_BASE<"insve.b", insve_v16i8, MSA128BOpnd>; -class INSVE_H_DESC : MSA_INSVE_DESC_BASE<"insve.h", int_mips_insve_h, +class INSVE_H_DESC : MSA_INSVE_DESC_BASE<"insve.h", insve_v8i16, MSA128HOpnd>; -class INSVE_W_DESC : MSA_INSVE_DESC_BASE<"insve.w", int_mips_insve_w, +class INSVE_W_DESC : MSA_INSVE_DESC_BASE<"insve.w", insve_v4i32, MSA128WOpnd>; -class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", int_mips_insve_d, +class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", insve_v2i64, MSA128DOpnd>; class LD_DESC_BASE; // Hardware register $29 - def HWR29 : MipsReg<29, "29">; + foreach I = 0-31 in + def HWR#I : MipsReg<#I, ""#I>; // Accum registers foreach I = 0-3 in @@ -364,7 +365,8 @@ def LO64 : RegisterClass<"Mips", [i64], 64, (add LO0_64)>; def HI64 : RegisterClass<"Mips", [i64], 64, (add HI0_64)>; // Hardware registers -def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>, Unallocatable; +def HWRegs : RegisterClass<"Mips", [i32], 32, (sequence "HWR%u", 0, 31)>, + Unallocatable; // Accumulator Registers def ACC64 : RegisterClass<"Mips", [untyped], 64, (add AC0)> { @@ -394,86 +396,68 @@ def OCTEON_P : RegisterClass<"Mips", [i64], 64, (add P0, P1, P2)>, // Register Operands. class MipsAsmRegOperand : AsmOperandClass { - let RenderMethod = "addRegAsmOperands"; -} -def GPR32AsmOperand : MipsAsmRegOperand { - let Name = "GPR32Asm"; - let ParserMethod = "parseGPR32"; + let ParserMethod = "ParseAnyRegister"; } def GPR64AsmOperand : MipsAsmRegOperand { - let Name = "GPR64Asm"; - let ParserMethod = "parseGPR64"; + let Name = "GPR64AsmReg"; + let PredicateMethod = "isGPRAsmReg"; +} + +def GPR32AsmOperand : MipsAsmRegOperand { + let Name = "GPR32AsmReg"; + let PredicateMethod = "isGPRAsmReg"; } def ACC64DSPAsmOperand : MipsAsmRegOperand { - let Name = "ACC64DSPAsm"; - let ParserMethod = "parseACC64DSP"; -} - -def LO32DSPAsmOperand : MipsAsmRegOperand { - let Name = "LO32DSPAsm"; - let ParserMethod = "parseLO32DSP"; + let Name = "ACC64DSPAsmReg"; + let PredicateMethod = "isACCAsmReg"; } def HI32DSPAsmOperand : MipsAsmRegOperand { - let Name = "HI32DSPAsm"; - let ParserMethod = "parseHI32DSP"; + let Name = "HI32DSPAsmReg"; + let PredicateMethod = "isACCAsmReg"; +} + +def LO32DSPAsmOperand : MipsAsmRegOperand { + let Name = "LO32DSPAsmReg"; + let PredicateMethod = "isACCAsmReg"; } def CCRAsmOperand : MipsAsmRegOperand { - let Name = "CCRAsm"; - let ParserMethod = "parseCCRRegs"; + let Name = "CCRAsmReg"; } def AFGR64AsmOperand : MipsAsmRegOperand { - let Name = "AFGR64Asm"; - let ParserMethod = "parseAFGR64Regs"; + let Name = "AFGR64AsmReg"; + let PredicateMethod = "isFGRAsmReg"; } def FGR64AsmOperand : MipsAsmRegOperand { - let Name = "FGR64Asm"; - let ParserMethod = "parseFGR64Regs"; + let Name = "FGR64AsmReg"; + let PredicateMethod = "isFGRAsmReg"; } def FGR32AsmOperand : MipsAsmRegOperand { - let Name = "FGR32Asm"; - let ParserMethod = "parseFGR32Regs"; + let Name = "FGR32AsmReg"; + let PredicateMethod = "isFGRAsmReg"; } def FGRH32AsmOperand : MipsAsmRegOperand { - let Name = "FGRH32Asm"; - let ParserMethod = "parseFGRH32Regs"; + let Name = "FGRH32AsmReg"; + let PredicateMethod = "isFGRAsmReg"; } def FCCRegsAsmOperand : MipsAsmRegOperand { - let Name = "FCCRegsAsm"; - let ParserMethod = "parseFCCRegs"; + let Name = "FCCAsmReg"; } -def MSA128BAsmOperand : MipsAsmRegOperand { - let Name = "MSA128BAsm"; - let ParserMethod = "parseMSA128BRegs"; +def MSA128AsmOperand : MipsAsmRegOperand { + let Name = "MSA128AsmReg"; } -def MSA128HAsmOperand : MipsAsmRegOperand { - let Name = "MSA128HAsm"; - let ParserMethod = "parseMSA128HRegs"; -} - -def MSA128WAsmOperand : MipsAsmRegOperand { - let Name = "MSA128WAsm"; - let ParserMethod = "parseMSA128WRegs"; -} - -def MSA128DAsmOperand : MipsAsmRegOperand { - let Name = "MSA128DAsm"; - let ParserMethod = "parseMSA128DRegs"; -} - -def MSA128CRAsmOperand : MipsAsmRegOperand { - let Name = "MSA128CRAsm"; - let ParserMethod = "parseMSA128CtrlRegs"; +def MSACtrlAsmOperand : MipsAsmRegOperand { + let Name = "MSACtrlAsmReg"; } def GPR32Opnd : RegisterOperand { @@ -493,13 +477,11 @@ def CCROpnd : RegisterOperand { } def HWRegsAsmOperand : MipsAsmRegOperand { - let Name = "HWRegsAsm"; - let ParserMethod = "parseHWRegs"; + let Name = "HWRegsAsmReg"; } def COP2AsmOperand : MipsAsmRegOperand { - let Name = "COP2Asm"; - let ParserMethod = "parseCOP2"; + let Name = "COP2AsmReg"; } def HWRegsOpnd : RegisterOperand { @@ -543,22 +525,22 @@ def COP2Opnd : RegisterOperand { } def MSA128BOpnd : RegisterOperand { - let ParserMatchClass = MSA128BAsmOperand; + let ParserMatchClass = MSA128AsmOperand; } def MSA128HOpnd : RegisterOperand { - let ParserMatchClass = MSA128HAsmOperand; + let ParserMatchClass = MSA128AsmOperand; } def MSA128WOpnd : RegisterOperand { - let ParserMatchClass = MSA128WAsmOperand; + let ParserMatchClass = MSA128AsmOperand; } def MSA128DOpnd : RegisterOperand { - let ParserMatchClass = MSA128DAsmOperand; + let ParserMatchClass = MSA128AsmOperand; } def MSA128CROpnd : RegisterOperand { - let ParserMatchClass = MSA128CRAsmOperand; + let ParserMatchClass = MSACtrlAsmOperand; } diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index 218cd15baa9..0dac0b79909 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -1810,6 +1810,13 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::mips_insert_d: return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(Op), Op->getValueType(0), Op->getOperand(1), Op->getOperand(3), Op->getOperand(2)); + case Intrinsic::mips_insve_b: + case Intrinsic::mips_insve_h: + case Intrinsic::mips_insve_w: + case Intrinsic::mips_insve_d: + return DAG.getNode(MipsISD::INSVE, DL, Op->getValueType(0), + Op->getOperand(1), Op->getOperand(2), Op->getOperand(3), + DAG.getConstant(0, MVT::i32)); case Intrinsic::mips_ldi_b: case Intrinsic::mips_ldi_h: case Intrinsic::mips_ldi_w: @@ -2837,7 +2844,8 @@ MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI, BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_W), Wd) .addReg(Wd_in) .addImm(Lane) - .addReg(Wt); + .addReg(Wt) + .addImm(0); MI->eraseFromParent(); // The pseudo instruction is gone now. return BB; @@ -2870,7 +2878,8 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI, BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_D), Wd) .addReg(Wd_in) .addImm(Lane) - .addReg(Wt); + .addReg(Wt) + .addImm(0); MI->eraseFromParent(); // The pseudo instruction is gone now. return BB; diff --git a/test/MC/Mips/cfi.s b/test/MC/Mips/cfi.s new file mode 100644 index 00000000000..a3247b5479a --- /dev/null +++ b/test/MC/Mips/cfi.s @@ -0,0 +1,13 @@ +# RUN: llvm-mc %s -triple=mips-unknown-unknown -show-encoding -mcpu=mips32 | \ +# RUN: FileCheck %s +# RUN: llvm-mc %s -triple=mips64-unknown-unknown -show-encoding -mcpu=mips64 | \ +# RUN: FileCheck %s + +# Check that we can accept register names in CFI directives and that they are +# canonicalised to their DWARF register numbers. + + .cfi_startproc # CHECK: .cfi_startproc + .cfi_register $6, $5 # CHECK: .cfi_register 6, 5 + .cfi_def_cfa $fp, 8 # CHECK: .cfi_def_cfa 30, 8 + .cfi_def_cfa $2, 16 # CHECK: .cfi_def_cfa 2, 16 + .cfi_endproc # CHECK: .cfi_endproc diff --git a/test/MC/Mips/mips-register-names-invalid.s b/test/MC/Mips/mips-register-names-invalid.s index df1054fed42..e6f8416a41e 100644 --- a/test/MC/Mips/mips-register-names-invalid.s +++ b/test/MC/Mips/mips-register-names-invalid.s @@ -4,5 +4,5 @@ # $32 used to trigger an assertion instead of the usual error message due to # an off-by-one bug. -# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction +# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction add $32, $0, $0 diff --git a/test/MC/Mips/mips3/valid-xfail.s b/test/MC/Mips/mips3/valid-xfail.s index dd4e482f381..7f802ef765f 100644 --- a/test/MC/Mips/mips3/valid-xfail.s +++ b/test/MC/Mips/mips3/valid-xfail.s @@ -8,10 +8,6 @@ # XFAIL: * .set noat - ddiv $zero,$k0,$s3 - ddivu $zero,$s0,$s1 - div $zero,$t9,$t3 - divu $zero,$t9,$t7 ehb lwc3 $10,-32265($k0) ssnop diff --git a/test/MC/Mips/mips3/valid.s b/test/MC/Mips/mips3/valid.s index f5c98f0007e..703d49a4ea7 100644 --- a/test/MC/Mips/mips3/valid.s +++ b/test/MC/Mips/mips3/valid.s @@ -35,8 +35,12 @@ dadd $s3,$at,$ra daddi $sp,$s4,-27705 daddiu $k0,$s6,-4586 + ddiv $zero,$k0,$s3 + ddivu $zero,$s0,$s1 + div $zero,$t9,$t3 div.d $f29,$f20,$f27 div.s $f4,$f5,$f15 + divu $zero,$t9,$t7 dmfc1 $t4,$f13 dmtc1 $s0,$f14 dmult $s7,$t1 diff --git a/test/MC/Mips/mips32r2/valid-xfail.s b/test/MC/Mips/mips32r2/valid-xfail.s index dff3ae43f1e..5dbb1d3b497 100644 --- a/test/MC/Mips/mips32r2/valid-xfail.s +++ b/test/MC/Mips/mips32r2/valid-xfail.s @@ -2,7 +2,7 @@ # they aren't implemented yet). # This test is set up to XPASS if any instruction generates an encoding. # -# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r2 | FileCheck %s +# RUN: not llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r2 | not FileCheck %s # CHECK-NOT: encoding # XFAIL: * @@ -48,7 +48,6 @@ c.nge.d $fcc5,$f21,$f16 c.nge.ps $f1,$f26 c.nge.s $fcc3,$f11,$f8 - c.ngl.d $f29,$f29 c.ngl.ps $f21,$f30 c.ngl.s $fcc2,$f31,$f23 c.ngle.ps $fcc7,$f12,$f20 @@ -66,7 +65,6 @@ c.seq.ps $fcc6,$f31,$f14 c.seq.s $fcc7,$f1,$f25 c.sf.ps $fcc6,$f4,$f6 - c.sf.s $f14,$f22 c.ueq.d $fcc4,$f13,$f25 c.ueq.ps $fcc1,$f5,$f29 c.ueq.s $fcc6,$f3,$f30 @@ -96,14 +94,10 @@ cmpu.lt.qb $at,$a3 ctcmsa $31,$s7 cvt.d.l $f4,$f16 - cvt.l.d $f24,$f15 - cvt.l.s $f11,$f29 cvt.ps.s $f3,$f18,$f19 cvt.s.l $f15,$f30 cvt.s.pl $f30,$f1 cvt.s.pu $f14,$f25 - div $zero,$t9,$t3 - divu $zero,$t9,$t7 dmt $k0 dpa.w.ph $ac1,$s7,$k0 dpaq_s.w.ph $ac2,$a0,$t5 @@ -152,8 +146,6 @@ flog2.w $w19,$w23 floor.l.d $f26,$f7 floor.l.s $f12,$f5 - floor.w.d $f14,$f11 - floor.w.s $f8,$f9 fork $s2,$t0,$a0 frcp.d $w12,$w4 frcp.w $w30,$w8 @@ -228,12 +220,8 @@ nlzc.d $w14,$w14 nlzc.h $w24,$w24 nlzc.w $w10,$w4 - nmadd.d $f18,$f9,$f14,$f19 nmadd.ps $f27,$f4,$f9,$f25 - nmadd.s $f0,$f5,$f25,$f12 - nmsub.d $f30,$f8,$f16,$f30 nmsub.ps $f6,$f12,$f14,$f17 - nmsub.s $f1,$f24,$f19,$f4 nor.v $w20,$w20,$w15 or.v $w13,$w23,$w12 packrl.ph $ra,$t8,$t6 @@ -264,7 +252,6 @@ pul.ps $f9,$f30,$f26 puu.ps $f24,$f9,$f2 raddu.w.qb $t9,$s3 - rdhwr $sp,$11 rdpgpr $s3,$t1 recip.d $f19,$f6 recip.s $f3,$f30 @@ -311,7 +298,6 @@ swe $t8,94($k0) swle $v1,-209($gp) swre $k0,-202($s2) - swxc1 $f19,$t4($k0) synci 20023($s0) tlbginv tlbginvf diff --git a/test/MC/Mips/mips32r2/valid.s b/test/MC/Mips/mips32r2/valid.s index 03f51554250..29c0807fff1 100644 --- a/test/MC/Mips/mips32r2/valid.s +++ b/test/MC/Mips/mips32r2/valid.s @@ -11,8 +11,10 @@ addi $t5,$t1,26322 addu $t1,$a0,$a2 and $s7,$v0,$t4 + c.ngl.d $f29,$f29 c.ngle.d $f0,$f16 c.sf.d $f30,$f0 + c.sf.s $f14,$f22 ceil.w.d $f11,$f25 ceil.w.s $f6,$f20 cfc1 $s1,$21 @@ -21,16 +23,22 @@ ctc1 $a2,$26 cvt.d.s $f22,$f28 cvt.d.w $f26,$f11 + cvt.l.d $f24,$f15 + cvt.l.s $f11,$f29 cvt.s.d $f26,$f8 cvt.s.w $f22,$f15 cvt.w.d $f20,$f14 cvt.w.s $f20,$f24 deret di $s8 + div $zero,$t9,$t3 div.d $f29,$f20,$f27 div.s $f4,$f5,$f15 + divu $zero,$t9,$t7 ei $t6 eret + floor.w.d $f14,$f11 + floor.w.s $f8,$f9 lb $t8,-14515($t2) lbu $t0,30195($v1) ldc1 $f11,16391($s0) @@ -94,9 +102,14 @@ multu $t1,$s2 neg.d $f27,$f18 neg.s $f1,$f15 + nmadd.d $f18,$f9,$f14,$f19 + nmadd.s $f0,$f5,$f25,$f12 + nmsub.d $f30,$f8,$f16,$f30 + nmsub.s $f1,$f24,$f19,$f4 nop nor $a3,$zero,$a3 or $t4,$s0,$sp + rdhwr $sp,$11 round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($t6) @@ -126,6 +139,7 @@ swc2 $25,24880($s0) swl $t7,13694($s3) swr $s1,-26590($t6) + swxc1 $f19,$t4($k0) teqi $s5,-17504 tgei $s1,5025 tgeiu $sp,-28621 diff --git a/test/MC/Mips/mips4/valid-xfail.s b/test/MC/Mips/mips4/valid-xfail.s index 7599164af0b..26749a91532 100644 --- a/test/MC/Mips/mips4/valid-xfail.s +++ b/test/MC/Mips/mips4/valid-xfail.s @@ -36,10 +36,6 @@ c.ult.s $fcc7,$f24,$f10 c.un.d $fcc6,$f23,$f24 c.un.s $fcc1,$f30,$f4 - ddiv $zero,$k0,$s3 - ddivu $zero,$s0,$s1 - div $zero,$t9,$t3 - divu $zero,$t9,$t7 ehb madd.d $f18,$f19,$f26,$f20 madd.s $f1,$f31,$f19,$f25 diff --git a/test/MC/Mips/mips4/valid.s b/test/MC/Mips/mips4/valid.s index 66886c5794e..bcc9f689bfa 100644 --- a/test/MC/Mips/mips4/valid.s +++ b/test/MC/Mips/mips4/valid.s @@ -35,8 +35,12 @@ dadd $s3,$at,$ra daddi $sp,$s4,-27705 daddiu $k0,$s6,-4586 + ddiv $zero,$k0,$s3 + ddivu $zero,$s0,$s1 + div $zero,$t9,$t3 div.d $f29,$f20,$f27 div.s $f4,$f5,$f15 + divu $zero,$t9,$t7 dmfc1 $t4,$f13 dmtc1 $s0,$f14 dmult $s7,$t1 diff --git a/test/MC/Mips/mips5/valid-xfail.s b/test/MC/Mips/mips5/valid-xfail.s index 10931587e45..285aabbfe6b 100644 --- a/test/MC/Mips/mips5/valid-xfail.s +++ b/test/MC/Mips/mips5/valid-xfail.s @@ -58,10 +58,6 @@ cvt.ps.s $f3,$f18,$f19 cvt.s.pl $f30,$f1 cvt.s.pu $f14,$f25 - ddiv $zero,$k0,$s3 - ddivu $zero,$s0,$s1 - div $zero,$t9,$t3 - divu $zero,$t9,$t7 ehb madd.d $f18,$f19,$f26,$f20 madd.ps $f22,$f3,$f14,$f3 diff --git a/test/MC/Mips/mips5/valid.s b/test/MC/Mips/mips5/valid.s index 7665d1f025e..64c2ff5e789 100644 --- a/test/MC/Mips/mips5/valid.s +++ b/test/MC/Mips/mips5/valid.s @@ -35,8 +35,12 @@ dadd $s3,$at,$ra daddi $sp,$s4,-27705 daddiu $k0,$s6,-4586 + ddiv $zero,$k0,$s3 + ddivu $zero,$s0,$s1 + div $zero,$t9,$t3 div.d $f29,$f20,$f27 div.s $f4,$f5,$f15 + divu $zero,$t9,$t7 dmfc1 $t4,$f13 dmtc1 $s0,$f14 dmult $s7,$t1 diff --git a/test/MC/Mips/mips64/valid-xfail.s b/test/MC/Mips/mips64/valid-xfail.s index 11ed7747b24..66f15e03c24 100644 --- a/test/MC/Mips/mips64/valid-xfail.s +++ b/test/MC/Mips/mips64/valid-xfail.s @@ -60,10 +60,6 @@ cvt.ps.s $f3,$f18,$f19 cvt.s.pl $f30,$f1 cvt.s.pu $f14,$f25 - ddiv $zero,$k0,$s3 - ddivu $zero,$s0,$s1 - div $zero,$t9,$t3 - divu $zero,$t9,$t7 dmfc0 $t2,c0_watchhi,2 dmtc0 $t7,c0_datalo ehb diff --git a/test/MC/Mips/mips64/valid.s b/test/MC/Mips/mips64/valid.s index cfd708ce667..673754535bc 100644 --- a/test/MC/Mips/mips64/valid.s +++ b/test/MC/Mips/mips64/valid.s @@ -39,8 +39,12 @@ dclo $s2,$a2 dclz $s0,$t9 deret + ddiv $zero,$k0,$s3 + ddivu $zero,$s0,$s1 + div $zero,$t9,$t3 div.d $f29,$f20,$f27 div.s $f4,$f5,$f15 + divu $zero,$t9,$t7 dmfc1 $t4,$f13 dmtc1 $s0,$f14 dmult $s7,$t1 diff --git a/test/MC/Mips/mips64r2/valid-xfail.s b/test/MC/Mips/mips64r2/valid-xfail.s index 7279707ea0b..d8aefd2a5c8 100644 --- a/test/MC/Mips/mips64r2/valid-xfail.s +++ b/test/MC/Mips/mips64r2/valid-xfail.s @@ -52,7 +52,6 @@ c.nge.d $fcc5,$f21,$f16 c.nge.ps $f1,$f26 c.nge.s $fcc3,$f11,$f8 - c.ngl.d $f29,$f29 c.ngl.ps $f21,$f30 c.ngl.s $fcc2,$f31,$f23 c.ngle.ps $fcc7,$f12,$f20 @@ -70,7 +69,6 @@ c.seq.ps $fcc6,$f31,$f14 c.seq.s $fcc7,$f1,$f25 c.sf.ps $fcc6,$f4,$f6 - c.sf.s $f14,$f22 c.ueq.d $fcc4,$f13,$f25 c.ueq.ps $fcc1,$f5,$f29 c.ueq.s $fcc6,$f3,$f30 @@ -98,10 +96,6 @@ cmpu.lt.qb $at,$a3 cvt.s.pl $f30,$f1 cvt.s.pu $f14,$f25 - ddiv $zero,$k0,$s3 - ddivu $zero,$s0,$s1 - div $zero,$t9,$t3 - divu $zero,$t9,$t7 dmfc0 $t2,c0_watchhi,2 dmfgc0 $gp,c0_perfcnt,6 dmt $k0 @@ -124,8 +118,6 @@ dpsu.h.qbr $ac2,$a1,$s6 dpsx.w.ph $ac0,$s7,$gp drorv $at,$a1,$s7 - dsbh $v1,$t6 - dshd $v0,$sp dvpe $s6 ehb emt $t0 @@ -188,7 +180,6 @@ lwx $t4,$t4($s4) madd.d $f18,$f19,$f26,$f20 madd.ps $f22,$f3,$f14,$f3 - madd.s $f1,$f31,$f19,$f25 maq_s.w.phl $ac2,$t9,$t3 maq_s.w.phr $ac0,$t2,$t9 maq_sa.w.phl $ac3,$a1,$v1 @@ -206,7 +197,6 @@ msub $ac2,$sp,$t6 msub.d $f10,$f1,$f31,$f18 msub.ps $f12,$f14,$f29,$f17 - msub.s $f12,$f19,$f10,$f16 msubu $ac2,$a1,$t8 mtc0 $t1,c0_datahi1 mtgc0 $s4,$21,7 @@ -236,10 +226,8 @@ nlzc.w $w10,$w4 nmadd.d $f18,$f9,$f14,$f19 nmadd.ps $f27,$f4,$f9,$f25 - nmadd.s $f0,$f5,$f25,$f12 nmsub.d $f30,$f8,$f16,$f30 nmsub.ps $f6,$f12,$f14,$f17 - nmsub.s $f1,$f24,$f19,$f4 nor.v $w20,$w20,$w15 or.v $w13,$w23,$w12 packrl.ph $ra,$t8,$t6 @@ -270,7 +258,6 @@ pul.ps $f9,$f30,$f26 puu.ps $f24,$f9,$f2 raddu.w.qb $t9,$s3 - rdhwr $sp,$11 rdpgpr $s3,$t1 recip.d $f19,$f6 recip.s $f3,$f30 @@ -282,8 +269,6 @@ rsqrt.s $f4,$f8 sbe $s7,33($s1) sce $sp,189($t2) - seb $t9,$t7 - seh $v1,$t4 she $t8,105($v0) shilo $ac1,26 shilov $ac2,$t2 @@ -330,6 +315,5 @@ tlbwi tlbwr wrpgpr $zero,$t5 - wsbh $k1,$t1 xor.v $w20,$w21,$w30 yield $v1,$s0 diff --git a/test/MC/Mips/mips64r2/valid.s b/test/MC/Mips/mips64r2/valid.s index e1d80199c34..4e549af9e79 100644 --- a/test/MC/Mips/mips64r2/valid.s +++ b/test/MC/Mips/mips64r2/valid.s @@ -11,8 +11,10 @@ addi $t5,$t1,26322 addu $t1,$a0,$a2 and $s7,$v0,$t4 + c.ngl.d $f29,$f29 c.ngle.d $f0,$f16 c.sf.d $f30,$f0 + c.sf.s $f14,$f22 ceil.l.d $f1,$f3 ceil.l.s $f18,$f13 ceil.w.d $f11,$f25 @@ -38,12 +40,18 @@ dclz $s0,$t9 deret di $s8 + ddiv $zero,$k0,$s3 + ddivu $zero,$s0,$s1 + div $zero,$t9,$t3 div.d $f29,$f20,$f27 div.s $f4,$f5,$f15 + divu $zero,$t9,$t7 dmfc1 $t4,$f13 dmtc1 $s0,$f14 dmult $s7,$t1 dmultu $a1,$a2 + dsbh $v1,$t6 + dshd $v0,$sp dsllv $zero,$s4,$t4 dsrav $gp,$s2,$s3 dsrlv $s3,$t6,$s4 @@ -79,6 +87,7 @@ lwxc1 $f12,$s1($s8) madd $s6,$t5 madd $zero,$t1 + madd.s $f1,$f31,$f19,$f25 maddu $s3,$gp maddu $t8,$s2 mfc0 $a2,$14,1 @@ -106,6 +115,7 @@ movz.d $f12,$f29,$t1 movz.s $f25,$f7,$v1 msub $s7,$k1 + msub.s $f12,$f19,$f10,$f16 msubu $t7,$a1 mtc1 $s8,$f9 mthc1 $zero,$f16 @@ -121,9 +131,12 @@ multu $t1,$s2 neg.d $f27,$f18 neg.s $f1,$f15 + nmadd.s $f0,$f5,$f25,$f12 + nmsub.s $f1,$f24,$f19,$f4 nop nor $a3,$zero,$a3 or $t4,$s0,$sp + rdhwr $sp,$11 round.l.d $f12,$f1 round.l.s $f25,$f5 round.w.d $f6,$f4 @@ -137,6 +150,8 @@ sdl $a3,-20961($s8) sdr $t3,-20423($t4) sdxc1 $f11,$t2($t6) + seb $t9,$t7 + seh $v1,$t4 sh $t6,-6704($t7) sllv $a3,$zero,$t1 slt $s7,$t3,$k1 @@ -169,3 +184,4 @@ trunc.w.d $f22,$f15 trunc.w.s $f28,$f30 xor $s2,$a0,$s8 + wsbh $k1,$t1 diff --git a/test/MC/Mips/set-at-directive-explicit-at.s b/test/MC/Mips/set-at-directive-explicit-at.s index 71f1a98fae4..1bd26ffa855 100644 --- a/test/MC/Mips/set-at-directive-explicit-at.s +++ b/test/MC/Mips/set-at-directive-explicit-at.s @@ -7,12 +7,12 @@ .text foo: # CHECK: jr $1 # encoding: [0x08,0x00,0x20,0x00] -# WARNINGS: :[[@LINE+2]]:12: warning: Used $at without ".set noat" +# WARNINGS: :[[@LINE+2]]:11: warning: Used $at without ".set noat" .set at=$1 jr $at # CHECK: jr $1 # encoding: [0x08,0x00,0x20,0x00] -# WARNINGS: :[[@LINE+2]]:12: warning: Used $at without ".set noat" +# WARNINGS: :[[@LINE+2]]:11: warning: Used $at without ".set noat" .set at=$1 jr $1 # WARNINGS-NOT: warning: Used $at without ".set noat" @@ -31,12 +31,12 @@ foo: jr $at # CHECK: jr $16 # encoding: [0x08,0x00,0x00,0x02] -# WARNINGS: :[[@LINE+2]]:12: warning: Used $16 with ".set at=$16" +# WARNINGS: :[[@LINE+2]]:11: warning: Used $16 with ".set at=$16" .set at=$16 jr $s0 # CHECK: jr $16 # encoding: [0x08,0x00,0x00,0x02] -# WARNINGS: :[[@LINE+2]]:12: warning: Used $16 with ".set at=$16" +# WARNINGS: :[[@LINE+2]]:11: warning: Used $16 with ".set at=$16" .set at=$16 jr $16 # WARNINGS-NOT: warning