diff options
Diffstat (limited to 'lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
-rw-r--r-- | lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 1314 |
1 files changed, 962 insertions, 352 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 3dd6562..cdae6c2 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -9,6 +9,7 @@ #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MipsRegisterInfo.h" +#include "MipsTargetStreamer.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -24,23 +25,25 @@ using namespace llvm; +namespace llvm { +class MCInstrInfo; +} + namespace { class MipsAssemblerOptions { public: - MipsAssemblerOptions(): - aTReg(1), reorder(true), macro(true) { - } + MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {} - unsigned getATRegNum() {return aTReg;} + unsigned getATRegNum() { return aTReg; } bool setATReg(unsigned Reg); - bool isReorder() {return reorder;} - void setReorder() {reorder = true;} - void setNoreorder() {reorder = false;} + bool isReorder() { return reorder; } + void setReorder() { reorder = true; } + void setNoreorder() { reorder = false; } - bool isMacro() {return macro;} - void setMacro() {macro = true;} - void setNomacro() {macro = false;} + bool isMacro() { return macro; } + void setMacro() { macro = true; } + void setNomacro() { macro = false; } private: unsigned aTReg; @@ -52,23 +55,21 @@ private: namespace { class MipsAsmParser : public MCTargetAsmParser { - enum FpFormatTy { - FP_FORMAT_NONE = -1, - FP_FORMAT_S, - FP_FORMAT_D, - FP_FORMAT_L, - FP_FORMAT_W - } FpFormat; + MipsTargetStreamer &getTargetStreamer() { + MCTargetStreamer &TS = Parser.getStreamer().getTargetStreamer(); + return static_cast<MipsTargetStreamer &>(TS); + } MCSubtargetInfo &STI; MCAsmParser &Parser; MipsAssemblerOptions Options; + bool hasConsumedDollar; #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, - SmallVectorImpl<MCParsedAsmOperand*> &Operands, + SmallVectorImpl<MCParsedAsmOperand *> &Operands, MCStreamer &Out, unsigned &ErrorInfo, bool MatchingInlineAsm); @@ -76,56 +77,98 @@ class MipsAsmParser : public MCTargetAsmParser { bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, - SmallVectorImpl<MCParsedAsmOperand*> &Operands); + SmallVectorImpl<MCParsedAsmOperand *> &Operands); bool ParseDirective(AsmToken DirectiveID); MipsAsmParser::OperandMatchResultTy - parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands, - int RegKind); + parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind); MipsAsmParser::OperandMatchResultTy - parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind); MipsAsmParser::OperandMatchResultTy - parseGPR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind); MipsAsmParser::OperandMatchResultTy - parseGPR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + bool parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind); MipsAsmParser::OperandMatchResultTy - parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); MipsAsmParser::OperandMatchResultTy - parseACRegsDSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseFGRH32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseMSA128BRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseMSA128HRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseMSA128WRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseMSA128DRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseMSA128CtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + MipsAsmParser::OperandMatchResultTy + parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands); bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind); - bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, + bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &, StringRef Mnemonic); int tryParseRegister(bool is64BitReg); - bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, + bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, bool is64BitReg); bool needsExpansion(MCInst &Inst); @@ -139,17 +182,19 @@ class MipsAsmParser : public MCTargetAsmParser { void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); void expandMemInst(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions, - bool isLoad,bool isImmOpnd); + SmallVectorImpl<MCInst> &Instructions, bool isLoad, + bool isImmOpnd); bool reportParseError(StringRef ErrorMsg); bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); bool parseRelocOperand(const MCExpr *&Res); - const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr); + const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr); bool isEvaluated(const MCExpr *Expr); bool parseDirectiveSet(); + bool parseDirectiveMipsHackStocg(); + bool parseDirectiveMipsHackELFFlags(); bool parseSetAtDirective(); bool parseSetNoAtDirective(); @@ -161,6 +206,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseSetAssignment(); bool parseDirectiveWord(unsigned Size, SMLoc L); + bool parseDirectiveGpWord(); MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol); @@ -172,40 +218,49 @@ class MipsAsmParser : public MCTargetAsmParser { return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0; } + bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; } + int matchRegisterName(StringRef Symbol, bool is64BitReg); int matchCPURegisterName(StringRef Symbol); int matchRegisterByNumber(unsigned RegNum, unsigned RegClass); - int matchFPURegisterName(StringRef Name, FpFormatTy Format); + int matchFPURegisterName(StringRef Name); - void setFpFormat(FpFormatTy Format) { - FpFormat = Format; - } + int matchFCCRegisterName(StringRef Name); - void setDefaultFpFormat(); + int matchACRegisterName(StringRef Name); - void setFpFormat(StringRef Format); + int matchMSA128RegisterName(StringRef Name); - FpFormatTy getFpFormat() {return FpFormat;} + int matchMSA128CtrlRegisterName(StringRef Name); + + int regKindToRegClass(int RegKind); unsigned getReg(int RC, int RegNo); int getATReg(); bool processInstruction(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + SmallVectorImpl<MCInst> &Instructions); + + // Helper function that checks if the value of a vector index is within the + // boundaries of accepted values for each RegisterKind + // Example: INSERT.B $w0[n], $1 => 16 > n >= 0 + bool validateMSAIndex(int Val, int RegKind); + public: - MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser) - : MCTargetAsmParser(), STI(sti), Parser(parser) { + MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, + const MCInstrInfo &MII) + : MCTargetAsmParser(), STI(sti), Parser(parser), + hasConsumedDollar(false) { // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); } MCAsmParser &getParser() const { return Parser; } MCAsmLexer &getLexer() const { return Parser.getLexer(); } - }; } @@ -221,13 +276,21 @@ public: Kind_GPR32, Kind_GPR64, Kind_HWRegs, - Kind_HW64Regs, Kind_FGR32Regs, + Kind_FGRH32Regs, Kind_FGR64Regs, Kind_AFGR64Regs, Kind_CCRRegs, Kind_FCCRegs, - Kind_ACRegsDSP + Kind_ACC64DSP, + Kind_LO32DSP, + Kind_HI32DSP, + Kind_COP2, + Kind_MSA128BRegs, + Kind_MSA128HRegs, + Kind_MSA128WRegs, + Kind_MSA128DRegs, + Kind_MSA128CtrlRegs }; private: @@ -238,7 +301,9 @@ private: k_Memory, k_PostIndexRegister, k_Register, - k_Token + k_PtrReg, + k_Token, + k_LSAImm } Kind; MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} @@ -277,7 +342,12 @@ public: Inst.addOperand(MCOperand::CreateReg(getReg())); } - void addExpr(MCInst &Inst, const MCExpr *Expr) const{ + void addPtrRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getPtrReg())); + } + + void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediate when possible. Null MCExpr = 0. if (Expr == 0) Inst.addOperand(MCOperand::CreateImm(0)); @@ -306,6 +376,9 @@ public: bool isImm() const { return Kind == k_Immediate; } bool isToken() const { return Kind == k_Token; } bool isMem() const { return Kind == k_Memory; } + bool isPtrReg() const { return Kind == k_PtrReg; } + bool isInvNum() const { return Kind == k_Immediate; } + bool isLSAImm() const { return Kind == k_LSAImm; } StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); @@ -317,13 +390,18 @@ public: return Reg.RegNum; } + unsigned getPtrReg() const { + assert((Kind == k_PtrReg) && "Invalid access!"); + return Reg.RegNum; + } + void setRegKind(RegisterKind RegKind) { - assert((Kind == k_Register) && "Invalid access!"); + assert((Kind == k_Register || Kind == k_PtrReg) && "Invalid access!"); Reg.Kind = RegKind; } const MCExpr *getImm() const { - assert((Kind == k_Immediate) && "Invalid access!"); + assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!"); return Imm.Val; } @@ -354,6 +432,14 @@ public: return Op; } + static MipsOperand *CreatePtrReg(unsigned RegNum, SMLoc S, SMLoc E) { + MipsOperand *Op = new MipsOperand(k_PtrReg); + Op->Reg.RegNum = RegNum; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { MipsOperand *Op = new MipsOperand(k_Immediate); Op->Imm.Val = Val; @@ -362,8 +448,16 @@ public: 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) { + SMLoc S, SMLoc E) { MipsOperand *Op = new MipsOperand(k_Memory); Op->Mem.Base = Base; Op->Mem.Off = Off; @@ -388,17 +482,12 @@ public: return Reg.Kind == Kind_HWRegs; } - bool isHW64RegsAsm() const { - assert((Kind == k_Register) && "Invalid access!"); - return Reg.Kind == Kind_HW64Regs; - } - bool isCCRAsm() const { assert((Kind == k_Register) && "Invalid access!"); return Reg.Kind == Kind_CCRRegs; } - bool isAFGR64Asm() const { + bool isAFGR64Asm() const { return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs; } @@ -410,28 +499,58 @@ public: return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs; } + bool isFGRH32Asm() const { + return (Kind == k_Register) && Reg.Kind == Kind_FGRH32Regs; + } + bool isFCCRegsAsm() const { return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs; } - bool isACRegsDSPAsm() const { - return Kind == k_Register && Reg.Kind == Kind_ACRegsDSP; + bool isACC64DSPAsm() const { + return Kind == k_Register && Reg.Kind == Kind_ACC64DSP; } - /// getStartLoc - Get the location of the first token of this operand. - SMLoc getStartLoc() const { - return StartLoc; + bool isLO32DSPAsm() const { + return Kind == k_Register && Reg.Kind == Kind_LO32DSP; } - /// getEndLoc - Get the location of the last token of this operand. - SMLoc getEndLoc() const { - return EndLoc; + + bool isHI32DSPAsm() const { + return Kind == k_Register && Reg.Kind == Kind_HI32DSP; + } + + bool isCOP2Asm() const { return Kind == k_Register && Reg.Kind == Kind_COP2; } + + bool isMSA128BAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128BRegs; + } + + bool isMSA128HAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128HRegs; + } + + bool isMSA128WAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128WRegs; + } + + bool isMSA128DAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128DRegs; } + bool isMSA128CRAsm() const { + return Kind == k_Register && Reg.Kind == Kind_MSA128CtrlRegs; + } + + /// getStartLoc - Get the location of the first token of this operand. + SMLoc getStartLoc() const { return StartLoc; } + /// getEndLoc - Get the location of the last token of this operand. + SMLoc getEndLoc() const { return EndLoc; } + virtual void print(raw_ostream &OS) const { llvm_unreachable("unimplemented!"); } }; // class MipsOperand -} // namespace +} // namespace namespace llvm { extern const MCInstrDesc MipsInsts[]; @@ -462,8 +581,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // reference or immediate we may have to expand instructions. for (unsigned i = 0; i < MCID.getNumOperands(); i++) { const MCOperandInfo &OpInfo = MCID.OpInfo[i]; - if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) - || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { + if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || + (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { MCOperand &Op = Inst.getOperand(i); if (Op.isImm()) { int MemOffset = Op.getImm(); @@ -476,7 +595,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, const MCExpr *Expr = Op.getExpr(); if (Expr->getKind() == MCExpr::SymbolRef) { const MCSymbolRefExpr *SR = - static_cast<const MCSymbolRefExpr*>(Expr); + static_cast<const MCSymbolRefExpr *>(Expr); if (SR->getKind() == MCSymbolRefExpr::VK_None) { // Expand symbol. expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); @@ -489,7 +608,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } } } // for - } // if load/store + } // if load/store if (needsExpansion(Inst)) expandInstruction(Inst, IDLoc, Instructions); @@ -512,7 +631,7 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) { } void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + SmallVectorImpl<MCInst> &Instructions) { switch (Inst.getOpcode()) { case Mips::LoadImm32Reg: return expandLoadImm(Inst, IDLoc, Instructions); @@ -567,8 +686,9 @@ void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, } } -void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { +void +MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; const MCOperand &ImmOp = Inst.getOperand(2); assert(ImmOp.isImm() && "expected immediate operand kind"); @@ -609,8 +729,9 @@ void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, } } -void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { +void +MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; const MCOperand &ImmOp = Inst.getOperand(1); assert(ImmOp.isImm() && "expected immediate operand kind"); @@ -643,14 +764,15 @@ void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, } void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) { + SmallVectorImpl<MCInst> &Instructions, + bool isLoad, bool isImmOpnd) { const MCSymbolRefExpr *SR; MCInst TempInst; unsigned ImmOffset, HiOffset, LoOffset; const MCExpr *ExprOffset; unsigned TmpRegNum; - unsigned AtRegNum = getReg((isMips64()) ? Mips::GPR64RegClassID - : Mips::GPR32RegClassID, getATReg()); + unsigned AtRegNum = getReg( + (isMips64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg()); // 1st operand is either the source or destination register. assert(Inst.getOperand(0).isReg() && "expected register operand kind"); unsigned RegOpNum = Inst.getOperand(0).getReg(); @@ -680,7 +802,7 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, TempInst.addOperand(MCOperand::CreateImm(HiOffset)); else { if (ExprOffset->getKind() == MCExpr::SymbolRef) { - SR = static_cast<const MCSymbolRefExpr*>(ExprOffset); + SR = static_cast<const MCSymbolRefExpr *>(ExprOffset); const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create( SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext()); @@ -723,15 +845,14 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, TempInst.clear(); } -bool MipsAsmParser:: -MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, - SmallVectorImpl<MCParsedAsmOperand*> &Operands, - MCStreamer &Out, unsigned &ErrorInfo, - bool MatchingInlineAsm) { +bool MipsAsmParser::MatchAndEmitInstruction( + SMLoc IDLoc, unsigned &Opcode, + SmallVectorImpl<MCParsedAsmOperand *> &Operands, MCStreamer &Out, + unsigned &ErrorInfo, bool MatchingInlineAsm) { MCInst Inst; SmallVector<MCInst, 8> Instructions; - unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, - MatchingInlineAsm); + unsigned MatchResult = + MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); switch (MatchResult) { default: @@ -752,7 +873,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, if (ErrorInfo >= Operands.size()) return Error(IDLoc, "too few operands for instruction"); - ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc(); + ErrorLoc = ((MipsOperand *)Operands[ErrorInfo])->getStartLoc(); if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; } @@ -766,44 +887,44 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, } int MipsAsmParser::matchCPURegisterName(StringRef Name) { - int CC; + int CC; if (Name == "at") return getATReg(); - CC = StringSwitch<unsigned>(Name) - .Case("zero", 0) - .Case("a0", 4) - .Case("a1", 5) - .Case("a2", 6) - .Case("a3", 7) - .Case("v0", 2) - .Case("v1", 3) - .Case("s0", 16) - .Case("s1", 17) - .Case("s2", 18) - .Case("s3", 19) - .Case("s4", 20) - .Case("s5", 21) - .Case("s6", 22) - .Case("s7", 23) - .Case("k0", 26) - .Case("k1", 27) - .Case("sp", 29) - .Case("fp", 30) - .Case("gp", 28) - .Case("ra", 31) - .Case("t0", 8) - .Case("t1", 9) - .Case("t2", 10) - .Case("t3", 11) - .Case("t4", 12) - .Case("t5", 13) - .Case("t6", 14) - .Case("t7", 15) - .Case("t8", 24) - .Case("t9", 25) - .Default(-1); + CC = StringSwitch<unsigned>(Name) + .Case("zero", 0) + .Case("a0", 4) + .Case("a1", 5) + .Case("a2", 6) + .Case("a3", 7) + .Case("v0", 2) + .Case("v1", 3) + .Case("s0", 16) + .Case("s1", 17) + .Case("s2", 18) + .Case("s3", 19) + .Case("s4", 20) + .Case("s5", 21) + .Case("s6", 22) + .Case("s7", 23) + .Case("k0", 26) + .Case("k1", 27) + .Case("sp", 29) + .Case("fp", 30) + .Case("gp", 28) + .Case("ra", 31) + .Case("t0", 8) + .Case("t1", 9) + .Case("t2", 10) + .Case("t3", 11) + .Case("t4", 12) + .Case("t5", 13) + .Case("t6", 14) + .Case("t7", 15) + .Case("t8", 24) + .Case("t9", 25) + .Default(-1); // Although SGI documentation just cuts out t0-t3 for n32/n64, // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7 @@ -813,72 +934,140 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) { if (CC == -1 && isMips64()) CC = StringSwitch<unsigned>(Name) - .Case("a4", 8) - .Case("a5", 9) - .Case("a6", 10) - .Case("a7", 11) - .Case("kt0", 26) - .Case("kt1", 27) - .Case("s8", 30) - .Default(-1); + .Case("a4", 8) + .Case("a5", 9) + .Case("a6", 10) + .Case("a7", 11) + .Case("kt0", 26) + .Case("kt1", 27) + .Case("s8", 30) + .Default(-1); return CC; } -int MipsAsmParser::matchFPURegisterName(StringRef Name, FpFormatTy Format) { +int MipsAsmParser::matchFPURegisterName(StringRef Name) { if (Name[0] == 'f') { StringRef NumString = Name.substr(1); unsigned IntVal; if (NumString.getAsInteger(10, IntVal)) - return -1; // This is not an integer. - if (IntVal > 31) + return -1; // This is not an integer. + if (IntVal > 31) // Maximum index for fpu register. return -1; + return IntVal; + } + return -1; +} - if (Format == FP_FORMAT_S || Format == FP_FORMAT_W) - return getReg(Mips::FGR32RegClassID, IntVal); - if (Format == FP_FORMAT_D) { - if (isFP64()) { - return getReg(Mips::FGR64RegClassID, IntVal); - } - // Only even numbers available as register pairs. - if ((IntVal > 31) || (IntVal % 2 != 0)) - return -1; - return getReg(Mips::AFGR64RegClassID, IntVal / 2); - } +int MipsAsmParser::matchFCCRegisterName(StringRef Name) { + + if (Name.startswith("fcc")) { + StringRef NumString = Name.substr(3); + unsigned IntVal; + if (NumString.getAsInteger(10, IntVal)) + return -1; // This is not an integer. + if (IntVal > 7) // There are only 8 fcc registers. + return -1; + return IntVal; } return -1; } -int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) { +int MipsAsmParser::matchACRegisterName(StringRef Name) { + + if (Name.startswith("ac")) { + StringRef NumString = Name.substr(2); + unsigned IntVal; + if (NumString.getAsInteger(10, IntVal)) + return -1; // This is not an integer. + if (IntVal > 3) // There are only 3 acc registers. + return -1; + return IntVal; + } + return -1; +} - if (Name.equals("fcc0")) - return Mips::FCC0; +int MipsAsmParser::matchMSA128RegisterName(StringRef Name) { + unsigned IntVal; + + if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal)) + return -1; + + if (IntVal > 31) + return -1; + + return IntVal; +} + +int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) { + int CC; + + CC = StringSwitch<unsigned>(Name) + .Case("msair", 0) + .Case("msacsr", 1) + .Case("msaaccess", 2) + .Case("msasave", 3) + .Case("msamodify", 4) + .Case("msarequest", 5) + .Case("msamap", 6) + .Case("msaunmap", 7) + .Default(-1); + + 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); - return matchFPURegisterName(Name, getFpFormat()); -} - -void MipsAsmParser::setDefaultFpFormat() { - - if (isMips64() || isFP64()) - FpFormat = FP_FORMAT_D; - else - FpFormat = FP_FORMAT_S; + CC = matchFPURegisterName(Name); + // TODO: decide about fpu register class + if (CC != -1) + return matchRegisterByNumber(CC, isFP64() ? Mips::FGR64RegClassID + : Mips::FGR32RegClassID); + return matchMSA128RegisterName(Name); } -void MipsAsmParser::setFpFormat(StringRef Format) { - - FpFormat = StringSwitch<FpFormatTy>(Format.lower()) - .Case(".s", FP_FORMAT_S) - .Case(".d", FP_FORMAT_D) - .Case(".l", FP_FORMAT_L) - .Case(".w", FP_FORMAT_W) - .Default(FP_FORMAT_NONE); +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) { @@ -889,17 +1078,15 @@ bool MipsAssemblerOptions::setATReg(unsigned Reg) { return true; } -int MipsAsmParser::getATReg() { - return Options.getATRegNum(); -} +int MipsAsmParser::getATReg() { return Options.getATRegNum(); } unsigned MipsAsmParser::getReg(int RC, int RegNo) { return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo); } int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) { - - if (RegNum > 31) + if (RegNum > + getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs()) return -1; return getReg(RegClass, RegNum); @@ -914,12 +1101,13 @@ int MipsAsmParser::tryParseRegister(bool is64BitReg) { RegNum = matchRegisterName(lowerCase, is64BitReg); } else if (Tok.is(AsmToken::Integer)) RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()), - is64BitReg ? Mips::GPR64RegClassID : Mips::GPR32RegClassID); + is64BitReg ? Mips::GPR64RegClassID + : Mips::GPR32RegClassID); return RegNum; } bool MipsAsmParser::tryParseRegisterOperand( - SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) { + SmallVectorImpl<MCParsedAsmOperand *> &Operands, bool is64BitReg) { SMLoc S = Parser.getTok().getLoc(); int RegNo = -1; @@ -928,14 +1116,15 @@ bool MipsAsmParser::tryParseRegisterOperand( if (RegNo == -1) return true; - Operands.push_back(MipsOperand::CreateReg(RegNo, S, - Parser.getTok().getLoc())); + Operands.push_back( + MipsOperand::CreateReg(RegNo, S, Parser.getTok().getLoc())); Parser.Lex(); // Eat register token. return false; } -bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, - StringRef Mnemonic) { +bool +MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + StringRef Mnemonic) { // 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); @@ -983,22 +1172,39 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, return true; SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier); - // Otherwise create a symbol reference. - const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, - getContext()); + const MCExpr *Res = + MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); Operands.push_back(MipsOperand::CreateImm(Res, S, E)); return false; } case AsmToken::Identifier: + // For instruction aliases like "bc1f $Label" dedicated parser will + // eat the '$' sign before failing. So in order to look for appropriate + // label we must check first if we have already consumed '$'. + if (hasConsumedDollar) { + hasConsumedDollar = false; + SMLoc S = Parser.getTok().getLoc(); + StringRef Identifier; + if (Parser.parseIdentifier(Identifier)) + return true; + SMLoc E = + SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier); + // Create a symbol reference. + const MCExpr *Res = + MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); + + Operands.push_back(MipsOperand::CreateImm(Res, S, E)); + return false; + } // Look for the existing symbol, we should check if // we need to assigne the propper RegisterKind. if (searchSymbolAlias(Operands, MipsOperand::Kind_None)) return false; - // Else drop to expression parsing. + // Else drop to expression parsing. case AsmToken::LParen: case AsmToken::Minus: case AsmToken::Plus: @@ -1029,7 +1235,7 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, return true; } -const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, +const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr) { const MCExpr *Res; // Check the type of the expression. @@ -1099,7 +1305,7 @@ bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { } bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { - Parser.Lex(); // Eat the % token. + Parser.Lex(); // Eat the % token. const AsmToken &Tok = Parser.getTok(); // Get next token, operation. if (Tok.isNot(AsmToken::Identifier)) return true; @@ -1145,7 +1351,7 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, StartLoc = Parser.getTok().getLoc(); RegNo = tryParseRegister(isMips64()); EndLoc = Parser.getTok().getLoc(); - return (RegNo == (unsigned) -1); + return (RegNo == (unsigned)-1); } bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { @@ -1177,11 +1383,12 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { } MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( - SmallVectorImpl<MCParsedAsmOperand*>&Operands) { + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { const MCExpr *IdVal = 0; SMLoc S; bool isParenExpr = false; + MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch; // First operand is the offset. S = Parser.getTok().getLoc(); @@ -1196,21 +1403,20 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( const AsmToken &Tok = Parser.getTok(); // Get the next token. if (Tok.isNot(AsmToken::LParen)) { - MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]); + MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]); if (Mnemonic->getToken() == "la") { - SMLoc E = SMLoc::getFromPointer( - Parser.getTok().getLoc().getPointer() - 1); + SMLoc E = + SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); return MatchOperand_Success; } if (Tok.is(AsmToken::EndOfStatement)) { - SMLoc E = SMLoc::getFromPointer( - Parser.getTok().getLoc().getPointer() - 1); + SMLoc E = + SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); // Zero register assumed, add a memory operand with ZERO as its base. - Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64 - : Mips::ZERO, - IdVal, S, E)); + Operands.push_back(MipsOperand::CreateMem( + isMips64() ? Mips::ZERO_64 : Mips::ZERO, IdVal, S, E)); return MatchOperand_Success; } Error(Parser.getTok().getLoc(), "'(' expected"); @@ -1220,21 +1426,12 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( Parser.Lex(); // Eat the '(' token. } - const AsmToken &Tok1 = Parser.getTok(); // Get next token - if (Tok1.is(AsmToken::Dollar)) { - Parser.Lex(); // Eat the '$' token. - if (tryParseRegisterOperand(Operands, isMips64())) { - Error(Parser.getTok().getLoc(), "unexpected token in operand"); - return MatchOperand_ParseFail; - } - - } else { - Error(Parser.getTok().getLoc(), "unexpected token in operand"); - return MatchOperand_ParseFail; - } + Res = parseRegs(Operands, isMips64() ? (int)MipsOperand::Kind_GPR64 + : (int)MipsOperand::Kind_GPR32); + if (Res != MatchOperand_Success) + return Res; - const AsmToken &Tok2 = Parser.getTok(); // Get next token. - if (Tok2.isNot(AsmToken::RParen)) { + if (Parser.getTok().isNot(AsmToken::RParen)) { Error(Parser.getTok().getLoc(), "')' expected"); return MatchOperand_ParseFail; } @@ -1247,7 +1444,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( IdVal = MCConstantExpr::Create(0, getContext()); // Replace the register operand with the memory operand. - MipsOperand* op = static_cast<MipsOperand*>(Operands.back()); + MipsOperand *op = static_cast<MipsOperand *>(Operands.back()); int RegNo = op->getReg(); // Remove the register from the operands. Operands.pop_back(); @@ -1266,31 +1463,150 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( return MatchOperand_Success; } +bool MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind) { + // If the first token is not '$' we have an error. + if (Parser.getTok().isNot(AsmToken::Dollar)) + return false; + + 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<MCParsedAsmOperand *> &Operands) { + MipsOperand::RegisterKind RegKind = + isN64() ? MipsOperand::Kind_GPR64 : MipsOperand::Kind_GPR32; + + // Parse index register. + if (!parsePtrReg(Operands, RegKind)) + return MatchOperand_NoMatch; + + // Parse '('. + if (Parser.getTok().isNot(AsmToken::LParen)) + return MatchOperand_NoMatch; + + Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc())); + Parser.Lex(); + + // Parse base register. + if (!parsePtrReg(Operands, RegKind)) + return MatchOperand_NoMatch; + + // Parse ')'. + if (Parser.getTok().isNot(AsmToken::RParen)) + return MatchOperand_NoMatch; + + Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc())); + Parser.Lex(); + + return MatchOperand_Success; +} + MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands, +MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind) { MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; - if (getLexer().getKind() == AsmToken::Identifier) { + 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)) + if (Parser.getTok().isNot(AsmToken::Dollar) && !hasConsumedDollar) return MatchOperand_NoMatch; - - Parser.Lex(); // Eat $ - if (!tryParseRegisterOperand(Operands, - RegKind == MipsOperand::Kind_GPR64)) { - // Set the proper register kind. - MipsOperand* op = static_cast<MipsOperand*>(Operands.back()); - op->setRegKind(Kind); - if ((Kind == MipsOperand::Kind_GPR32) - && (getLexer().is(AsmToken::LParen))) { + 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) + if (parseRegs(Operands, RegKind) != MatchOperand_Success) return MatchOperand_NoMatch; if (getLexer().isNot(AsmToken::RParen)) return MatchOperand_NoMatch; @@ -1302,49 +1618,254 @@ MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 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::parseGPR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { +MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + int RegKind) { + MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; + SMLoc S = Parser.getTok().getLoc(); + std::string RegName; - if (!isMips64()) + 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<MipsOperand *>(Operands[0]); + + Operands.push_back(MipsOperand::CreateToken("[", Parser.getTok().getLoc())); + Parser.Lex(); // Parse the '[' token. + + if (Parser.getTok().is(AsmToken::Dollar)) { + // This must be a GPR. + MipsOperand *RegOp; + SMLoc VIdx = Parser.getTok().getLoc(); + Parser.Lex(); // Parse the '$' token. + + // GPR have aliases and we must account for that. Example: $30 == $fp + if (getLexer().getKind() == AsmToken::Integer) { + unsigned RegNum = Parser.getTok().getIntVal(); + int Reg = matchRegisterByNumber( + RegNum, regKindToRegClass(MipsOperand::Kind_GPR32)); + if (Reg == -1) { + Error(VIdx, "invalid general purpose register"); + return MatchOperand_ParseFail; + } + + RegOp = MipsOperand::CreateReg(Reg, VIdx, Parser.getTok().getLoc()); + } else if (getLexer().getKind() == AsmToken::Identifier) { + int RegNum = -1; + std::string RegName = Parser.getTok().getString().lower(); + + RegNum = matchCPURegisterName(RegName); + if (RegNum == -1) { + Error(VIdx, "general purpose register expected"); + return MatchOperand_ParseFail; + } + RegNum = getReg(regKindToRegClass(MipsOperand::Kind_GPR32), RegNum); + RegOp = MipsOperand::CreateReg(RegNum, VIdx, Parser.getTok().getLoc()); + } else + return MatchOperand_ParseFail; + + RegOp->setRegKind(MipsOperand::Kind_GPR32); + Operands.push_back(RegOp); + Parser.Lex(); // Eat the register identifier. + + if (Parser.getTok().isNot(AsmToken::RBrac)) + return MatchOperand_ParseFail; + + Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc())); + Parser.Lex(); // Parse the ']' token. + + return MatchOperand_Success; + } + + // The index must be a constant expression then. + SMLoc VIdx = Parser.getTok().getLoc(); + const MCExpr *ImmVal; + + if (getParser().parseExpression(ImmVal)) + return MatchOperand_ParseFail; + + const MCConstantExpr *expr = dyn_cast<MCConstantExpr>(ImmVal); + if (!expr || !validateMSAIndex((int)expr->getValue(), Kind)) { + Error(VIdx, "invalid immediate value"); + return MatchOperand_ParseFail; + } + + 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<MCParsedAsmOperand *> &Operands, + int RegKind) { + MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; + + if (Kind != MipsOperand::Kind_MSA128CtrlRegs) return MatchOperand_NoMatch; - return parseRegs(Operands, (int) MipsOperand::Kind_GPR64); + + 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::parseGPR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - return parseRegs(Operands, (int) MipsOperand::Kind_GPR32); +MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + + if (!isMips64()) + return MatchOperand_NoMatch; + return parseRegs(Operands, (int)MipsOperand::Kind_GPR64); } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { +MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_GPR32); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAFGR64Regs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { if (isFP64()) return MatchOperand_NoMatch; - // Double operand is expected, set appropriate format - setFpFormat(FP_FORMAT_D); - - return parseRegs(Operands, (int) MipsOperand::Kind_AFGR64Regs); + return parseRegs(Operands, (int)MipsOperand::Kind_AFGR64Regs); } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { +MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { if (!isFP64()) return MatchOperand_NoMatch; - // Double operand is expected, set appropriate format - setFpFormat(FP_FORMAT_D); + return parseRegs(Operands, (int)MipsOperand::Kind_FGR64Regs); +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_FGR32Regs); +} - return parseRegs(Operands, (int) MipsOperand::Kind_FGR64Regs); +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseFGRH32Regs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_FGRH32Regs); } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - // Single operand is expected, set appropriate format - setFpFormat(FP_FORMAT_S); - return parseRegs(Operands, (int) MipsOperand::Kind_FGR32Regs); +MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_FCCRegs); } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { +MipsAsmParser::parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_ACC64DSP); +} + +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { // If the first token is not '$' we have an error. if (Parser.getTok().isNot(AsmToken::Dollar)) return MatchOperand_NoMatch; @@ -1357,19 +1878,19 @@ MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { if (Tok.isNot(AsmToken::Identifier)) return MatchOperand_NoMatch; - if (!Tok.getIdentifier().startswith("fcc")) + if (!Tok.getIdentifier().startswith("ac")) return MatchOperand_NoMatch; - StringRef NumString = Tok.getIdentifier().substr(3); + StringRef NumString = Tok.getIdentifier().substr(2); unsigned IntVal; if (NumString.getAsInteger(10, IntVal)) return MatchOperand_NoMatch; - unsigned Reg = matchRegisterByNumber(IntVal, Mips::FCCRegClassID); + unsigned Reg = matchRegisterByNumber(IntVal, Mips::LO32DSPRegClassID); MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); - Op->setRegKind(MipsOperand::Kind_FCCRegs); + Op->setRegKind(MipsOperand::Kind_LO32DSP); Operands.push_back(Op); Parser.Lex(); // Eat the register number. @@ -1377,7 +1898,7 @@ MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseACRegsDSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { +MipsAsmParser::parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { // If the first token is not '$' we have an error. if (Parser.getTok().isNot(AsmToken::Dollar)) return MatchOperand_NoMatch; @@ -1390,27 +1911,78 @@ MipsAsmParser::parseACRegsDSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { if (Tok.isNot(AsmToken::Identifier)) return MatchOperand_NoMatch; - if (!Tok.getIdentifier().startswith("acc")) + if (!Tok.getIdentifier().startswith("ac")) return MatchOperand_NoMatch; - StringRef NumString = Tok.getIdentifier().substr(3); + StringRef NumString = Tok.getIdentifier().substr(2); unsigned IntVal; if (NumString.getAsInteger(10, IntVal)) return MatchOperand_NoMatch; - unsigned Reg = matchRegisterByNumber(IntVal, Mips::ACRegsDSPRegClassID); + unsigned Reg = matchRegisterByNumber(IntVal, Mips::HI32DSPRegClassID); MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); - Op->setRegKind(MipsOperand::Kind_ACRegsDSP); + Op->setRegKind(MipsOperand::Kind_HI32DSP); Operands.push_back(Op); Parser.Lex(); // Eat the register number. return MatchOperand_Success; } +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + // If the first token is not '$' we have an error. + if (Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_NoMatch; + + SMLoc S = Parser.getTok().getLoc(); + Parser.Lex(); // Eat the '$' + + const AsmToken &Tok = Parser.getTok(); // Get next token. + + if (Tok.isNot(AsmToken::Integer)) + return MatchOperand_NoMatch; + + unsigned IntVal = Tok.getIntVal(); + + unsigned Reg = matchRegisterByNumber(IntVal, Mips::COP2RegClassID); + + MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); + Op->setRegKind(MipsOperand::Kind_COP2); + Operands.push_back(Op); + + Parser.Lex(); // Eat the register number. + return MatchOperand_Success; +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128BRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128BRegs); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128HRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128HRegs); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128WRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128WRegs); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128DRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128DRegs); +} + +MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128CtrlRegs( + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseMSACtrlRegs(Operands, (int)MipsOperand::Kind_MSA128CtrlRegs); +} + bool MipsAsmParser::searchSymbolAlias( - SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind) { + SmallVectorImpl<MCParsedAsmOperand *> &Operands, unsigned RegKind) { MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier()); if (Sym) { @@ -1421,38 +1993,39 @@ bool MipsAsmParser::searchSymbolAlias( else return false; if (Expr->getKind() == MCExpr::SymbolRef) { - MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind) RegKind; - const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr); + MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; + const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); const StringRef DefSymbol = Ref->getSymbol().getName(); if (DefSymbol.startswith("$")) { int RegNum = -1; APInt IntVal(32, -1); if (!DefSymbol.substr(1).getAsInteger(10, IntVal)) RegNum = matchRegisterByNumber(IntVal.getZExtValue(), - isMips64() - ? Mips::GPR64RegClassID - : Mips::GPR32RegClassID); + isMips64() ? 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), FP_FORMAT_D); + RegNum = matchFPURegisterName(DefSymbol.substr(1)); break; case MipsOperand::Kind_FGR32Regs: - RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_S); + RegNum = matchFPURegisterName(DefSymbol.substr(1)); break; case MipsOperand::Kind_GPR64: case MipsOperand::Kind_GPR32: default: - RegNum = matchRegisterName(DefSymbol.substr(1), isMips64()); + 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()); + MipsOperand *op = + MipsOperand::CreateReg(RegNum, S, Parser.getTok().getLoc()); op->setRegKind(Kind); Operands.push_back(op); return true; @@ -1460,9 +2033,9 @@ bool MipsAsmParser::searchSymbolAlias( } } else if (Expr->getKind() == MCExpr::Constant) { Parser.Lex(); - const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr); - MipsOperand *op = MipsOperand::CreateImm(Const, S, - Parser.getTok().getLoc()); + const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr); + MipsOperand *op = + MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc()); Operands.push_back(op); return true; } @@ -1471,115 +2044,101 @@ bool MipsAsmParser::searchSymbolAlias( } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - - // If the first token is not '$' we have 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 the next token. - if (Tok.isNot(AsmToken::Integer)) - return MatchOperand_NoMatch; - - unsigned RegNum = Tok.getIntVal(); - // At the moment only hwreg29 is supported. - if (RegNum != 29) - return MatchOperand_ParseFail; - - MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S, - Parser.getTok().getLoc()); - op->setRegKind(MipsOperand::Kind_HWRegs); - Operands.push_back(op); - - Parser.Lex(); // Eat the register number. - return MatchOperand_Success; +MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_HWRegs); } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseHW64Regs( - SmallVectorImpl<MCParsedAsmOperand*> &Operands) { +MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + return parseRegs(Operands, (int)MipsOperand::Kind_CCRRegs); +} - if (!isMips64()) - return MatchOperand_NoMatch; - // If the first token is not '$' we have an error. - if (Parser.getTok().isNot(AsmToken::Dollar)) +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + const MCExpr *IdVal; + // If the first token is '$' we may have register operand. + if (Parser.getTok().is(AsmToken::Dollar)) return MatchOperand_NoMatch; SMLoc S = Parser.getTok().getLoc(); - Parser.Lex(); // Eat $ - - const AsmToken &Tok = Parser.getTok(); // Get the next token. - if (Tok.isNot(AsmToken::Integer)) - return MatchOperand_NoMatch; - - unsigned RegNum = Tok.getIntVal(); - // At the moment only hwreg29 is supported. - if (RegNum != 29) + if (getParser().parseExpression(IdVal)) return MatchOperand_ParseFail; - - MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S, - Parser.getTok().getLoc()); - op->setRegKind(MipsOperand::Kind_HW64Regs); - Operands.push_back(op); - - Parser.Lex(); // Eat the register number. + const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal); + assert(MCE && "Unexpected MCExpr type."); + 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)); return MatchOperand_Success; } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - // If the first token is not '$' we have an error. - if (Parser.getTok().isNot(AsmToken::Dollar)) +MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + switch (getLexer().getKind()) { + default: return MatchOperand_NoMatch; + case AsmToken::LParen: + case AsmToken::Plus: + case AsmToken::Minus: + case AsmToken::Integer: + break; + } + const MCExpr *Expr; 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; + if (getParser().parseExpression(Expr)) + return MatchOperand_ParseFail; - unsigned Reg = matchRegisterByNumber(Tok.getIntVal(), Mips::CCRRegClassID); + int64_t Val; + if (!Expr->EvaluateAsAbsolute(Val)) { + Error(S, "expected immediate value"); + return MatchOperand_ParseFail; + } - MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc()); - Op->setRegKind(MipsOperand::Kind_CCRRegs); - Operands.push_back(Op); + // The LSA instruction allows a 2-bit unsigned immediate. For this reason + // and because the CPU always adds one to the immediate field, the allowed + // range becomes 1..4. We'll only check the range here and will deal + // with the addition/subtraction when actually decoding/encoding + // the instruction. + if (Val < 1 || Val > 4) { + Error(S, "immediate not in range (1..4)"); + return MatchOperand_ParseFail; + } - Parser.Lex(); // Eat the register number. + Operands.push_back(MipsOperand::CreateLSAImm(Expr, S, + Parser.getTok().getLoc())); return MatchOperand_Success; } MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { - MCSymbolRefExpr::VariantKind VK - = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol) - .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI) - .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO) - .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL) - .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL) - .Case("got", MCSymbolRefExpr::VK_Mips_GOT) - .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD) - .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM) - .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI) - .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO) - .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL) - .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI) - .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO) - .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP) - .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE) - .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST) - .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI) - .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO) - .Default(MCSymbolRefExpr::VK_None); + MCSymbolRefExpr::VariantKind VK = + StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol) + .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI) + .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO) + .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL) + .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL) + .Case("got", MCSymbolRefExpr::VK_Mips_GOT) + .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD) + .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM) + .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI) + .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO) + .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL) + .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI) + .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO) + .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP) + .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE) + .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST) + .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI) + .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO) + .Default(MCSymbolRefExpr::VK_None); return VK; } -bool MipsAsmParser:: -ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, - SmallVectorImpl<MCParsedAsmOperand*> &Operands) { +bool MipsAsmParser::ParseInstruction( + ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, + SmallVectorImpl<MCParsedAsmOperand *> &Operands) { // Check if we have valid mnemonic if (!mnemonicIsValid(Name, 0)) { Parser.eatToEndOfStatement(); @@ -1757,12 +2316,13 @@ bool MipsAsmParser::parseSetAssignment() { // We have a '$' followed by something, make sure they are adjacent. if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer()) return true; - StringRef Res = StringRef(DollarLoc.getPointer(), - getTok().getEndLoc().getPointer() - DollarLoc.getPointer()); + StringRef Res = + StringRef(DollarLoc.getPointer(), + getTok().getEndLoc().getPointer() - DollarLoc.getPointer()); Symbol = getContext().GetOrCreateSymbol(Res); Parser.Lex(); - Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, - getContext()); + Value = + MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, getContext()); } else if (Parser.parseExpression(Value)) return reportParseError("expected valid expression after comma"); @@ -1810,6 +2370,34 @@ bool MipsAsmParser::parseDirectiveSet() { return true; } +bool MipsAsmParser::parseDirectiveMipsHackStocg() { + MCAsmParser &Parser = getParser(); + StringRef Name; + if (Parser.parseIdentifier(Name)) + reportParseError("expected identifier"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token"); + Lex(); + + int64_t Flags = 0; + if (Parser.parseAbsoluteExpression(Flags)) + return TokError("unexpected token"); + + getTargetStreamer().emitMipsHackSTOCG(Sym, Flags); + return false; +} + +bool MipsAsmParser::parseDirectiveMipsHackELFFlags() { + int64_t Flags = 0; + if (Parser.parseAbsoluteExpression(Flags)) + return TokError("unexpected token"); + + getTargetStreamer().emitMipsHackELFFlags(Flags); + return false; +} + /// parseDirectiveWord /// ::= .word [ expression (, expression)* ] bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) { @@ -1835,6 +2423,22 @@ bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) { return false; } +/// parseDirectiveGpWord +/// ::= .gpword local_sym +bool MipsAsmParser::parseDirectiveGpWord() { + const MCExpr *Value; + // EmitGPRel32Value requires an expression, so we are using base class + // method to evaluate the expression. + if (getParser().parseExpression(Value)) + return true; + getParser().getStreamer().EmitGPRel32Value(Value); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(getLexer().getLoc(), "unexpected token in directive"); + Parser.Lex(); // Eat EndOfStatement token. + return false; +} + bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { StringRef IDVal = DirectiveID.getString(); @@ -1875,7 +2479,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { if (IDVal == ".gpword") { // Ignore this directive for now. - Parser.eatToEndOfStatement(); + parseDirectiveGpWord(); return false; } @@ -1884,6 +2488,12 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } + if (IDVal == ".mips_hack_stocg") + return parseDirectiveMipsHackStocg(); + + if (IDVal == ".mips_hack_elf_flags") + return parseDirectiveMipsHackELFFlags(); + return true; } |