Revert: [mips] Rewrite MipsAsmParser and MipsOperand.' due to buildbot errors in...
authorDaniel Sanders <daniel.sanders@imgtec.com>
Mon, 31 Mar 2014 18:51:43 +0000 (18:51 +0000)
committerDaniel Sanders <daniel.sanders@imgtec.com>
Mon, 31 Mar 2014 18:51:43 +0000 (18:51 +0000)
It's currently unable to parse 'sym + imm' without surrounding parenthesis.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205237 91177308-0d34-0410-b5e6-96231b3b80d8

23 files changed:
lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/Disassembler/MipsDisassembler.cpp
lib/Target/Mips/MipsISelLowering.cpp
lib/Target/Mips/MipsISelLowering.h
lib/Target/Mips/MipsInstrInfo.td
lib/Target/Mips/MipsMSAInstrInfo.td
lib/Target/Mips/MipsRegisterInfo.td
lib/Target/Mips/MipsSEISelLowering.cpp
test/MC/Mips/cfi.s [deleted file]
test/MC/Mips/mips-register-names-invalid.s
test/MC/Mips/mips3/valid-xfail.s
test/MC/Mips/mips3/valid.s
test/MC/Mips/mips32r2/valid-xfail.s
test/MC/Mips/mips32r2/valid.s
test/MC/Mips/mips4/valid-xfail.s
test/MC/Mips/mips4/valid.s
test/MC/Mips/mips5/valid-xfail.s
test/MC/Mips/mips5/valid.s
test/MC/Mips/mips64/valid-xfail.s
test/MC/Mips/mips64/valid.s
test/MC/Mips/mips64r2/valid-xfail.s
test/MC/Mips/mips64r2/valid.s
test/MC/Mips/set-at-directive-explicit-at.s

index 95e7d09ce0c7271a4aa736dda8f146276d027eb3..2b80d3f03de30a3aa04af1f39a96677f012f8da8 100644 (file)
@@ -23,7 +23,6 @@
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCTargetAsmParser.h"
-#include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/TargetRegistry.h"
 
@@ -58,6 +57,7 @@ private:
 
 namespace {
 class MipsAsmParser : public MCTargetAsmParser {
+
   MipsTargetStreamer &getTargetStreamer() {
     MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
     return static_cast<MipsTargetStreamer &>(TS);
@@ -66,6 +66,7 @@ class MipsAsmParser : public MCTargetAsmParser {
   MCSubtargetInfo &STI;
   MCAsmParser &Parser;
   MipsAssemblerOptions Options;
+  bool hasConsumedDollar;
 
 #define GET_ASSEMBLER_HEADER
 #include "MipsGenAsmMatcher.inc"
@@ -75,52 +76,104 @@ class MipsAsmParser : public MCTargetAsmParser {
                                MCStreamer &Out, unsigned &ErrorInfo,
                                bool MatchingInlineAsm);
 
-  /// Parse a register as used in CFI directives
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
 
-  bool ParseParenSuffix(StringRef Name,
-                        SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
-  bool ParseBracketSuffix(StringRef Name,
-                          SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc,
                         SmallVectorImpl<MCParsedAsmOperand *> &Operands);
 
   bool ParseDirective(AsmToken DirectiveID);
 
+  MipsAsmParser::OperandMatchResultTy
+  parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+                   int RegKind);
+
   MipsAsmParser::OperandMatchResultTy
   parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
 
-  MipsAsmParser::OperandMatchResultTy MatchAnyRegisterNameWithoutDollar(
-      SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
-      SMLoc S);
+  bool parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+                   int RegKind);
+
+  MipsAsmParser::OperandMatchResultTy
+  parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseFGRH32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+
+  MipsAsmParser::OperandMatchResultTy
+  parseMSA128BRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
 
   MipsAsmParser::OperandMatchResultTy
-  ParseAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
-                                SMLoc S);
+  parseMSA128HRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
 
   MipsAsmParser::OperandMatchResultTy
-  ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+  parseMSA128WRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
 
   MipsAsmParser::OperandMatchResultTy
-  ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+  parseMSA128DRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
 
   MipsAsmParser::OperandMatchResultTy
-  ParseJumpTarget(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+  parseMSA128CtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
 
   MipsAsmParser::OperandMatchResultTy
   parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
 
   MipsAsmParser::OperandMatchResultTy
-  ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+  parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
 
-  bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+  bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+                         unsigned RegKind);
 
   bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
                     StringRef Mnemonic);
 
+  int tryParseRegister(bool is64BitReg);
+
+  bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+                               bool is64BitReg);
+
   bool needsExpansion(MCInst &Inst);
 
   void expandInstruction(MCInst &Inst, SMLoc IDLoc,
@@ -182,6 +235,8 @@ class MipsAsmParser : public MCTargetAsmParser {
 
   bool eatComma(StringRef ErrorStr);
 
+  int matchRegisterName(StringRef Symbol, bool is64BitReg);
+
   int matchCPURegisterName(StringRef Symbol);
 
   int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
@@ -196,12 +251,17 @@ class MipsAsmParser : public MCTargetAsmParser {
 
   int matchMSA128CtrlRegisterName(StringRef Name);
 
+  int regKindToRegClass(int RegKind);
+
   unsigned getReg(int RC, int RegNo);
 
   unsigned getGPR(int RegNo);
 
   int getATReg();
 
+  // Warn if RegNo is the current assembler temporary.
+  void warnIfAssemblerTemporary(int RegNo);
+
   bool processInstruction(MCInst &Inst, SMLoc IDLoc,
                           SmallVectorImpl<MCInst> &Instructions);
 
@@ -227,7 +287,8 @@ class MipsAsmParser : public MCTargetAsmParser {
 public:
   MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
                 const MCInstrInfo &MII)
-      : MCTargetAsmParser(), STI(sti), Parser(parser) {
+      : MCTargetAsmParser(), STI(sti), Parser(parser),
+        hasConsumedDollar(false) {
     // Initialize the set of available features.
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
 
@@ -240,9 +301,6 @@ public:
 
   MCAsmParser &getParser() const { return Parser; }
   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
-
-  /// Warn if RegNo is the current assembler temporary.
-  void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
 };
 }
 
@@ -251,56 +309,53 @@ namespace {
 /// MipsOperand - Instances of this class represent a parsed Mips machine
 /// instruction.
 class MipsOperand : public MCParsedAsmOperand {
+
 public:
-  /// Broad categories of register classes
-  /// The exact class is finalized by the render method.
-  enum RegKind {
-    RegKind_GPR = 1,      /// GPR32 and GPR64 (depending on isGP64())
-    RegKind_FGR = 2,      /// FGR32, FGR64, AFGR64 (depending on context and
-                          /// isFP64())
-    RegKind_FCC = 4,      /// FCC
-    RegKind_MSA128 = 8,   /// MSA128[BHWD] (makes no difference which)
-    RegKind_MSACtrl = 16, /// MSA control registers
-    RegKind_COP2 = 32,    /// COP2
-    RegKind_ACC = 64,     /// HI32DSP, LO32DSP, and ACC64DSP (depending on
-                          /// context).
-    RegKind_CCR = 128,    /// CCR
-    RegKind_HWRegs = 256, /// HWRegs
-
-    /// Potentially any (e.g. $1)
-    RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
-                      RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
-                      RegKind_CCR | RegKind_HWRegs
+  enum RegisterKind {
+    Kind_None,
+    Kind_GPR32,
+    Kind_GPR64,
+    Kind_HWRegs,
+    Kind_FGR32Regs,
+    Kind_FGRH32Regs,
+    Kind_FGR64Regs,
+    Kind_AFGR64Regs,
+    Kind_CCRRegs,
+    Kind_FCCRegs,
+    Kind_ACC64DSP,
+    Kind_LO32DSP,
+    Kind_HI32DSP,
+    Kind_COP2,
+    Kind_MSA128BRegs,
+    Kind_MSA128HRegs,
+    Kind_MSA128WRegs,
+    Kind_MSA128DRegs,
+    Kind_MSA128CtrlRegs
   };
 
 private:
   enum KindTy {
+    k_CondCode,
+    k_CoprocNum,
     k_Immediate,
     k_Memory,
-    k_PhysRegister,
-    k_RegisterIndex,
-    k_Token
+    k_PostIndexRegister,
+    k_Register,
+    k_PtrReg,
+    k_Token,
+    k_LSAImm
   } Kind;
 
-  MipsOperand(KindTy K, MipsAsmParser &Parser)
-      : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
-
-  /// For diagnostics, and checking the assembler temporary
-  MipsAsmParser &AsmParser;
+  MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
 
   struct Token {
     const char *Data;
     unsigned Length;
   };
 
-  struct PhysRegOp {
-    unsigned Num; /// Register Number
-  };
-
-  struct RegIdxOp {
-    unsigned Index; /// Index into the register class
-    RegKind Kind;   /// Bitfield of the kinds it could possibly be
-    const MCRegisterInfo *RegInfo;
+  struct RegOp {
+    unsigned RegNum;
+    RegisterKind Kind;
   };
 
   struct ImmOp {
@@ -308,161 +363,30 @@ private:
   };
 
   struct MemOp {
-    MipsOperand *Base;
+    unsigned Base;
     const MCExpr *Off;
   };
 
   union {
     struct Token Tok;
-    struct PhysRegOp PhysReg;
-    struct RegIdxOp RegIdx;
+    struct RegOp Reg;
     struct ImmOp Imm;
     struct MemOp Mem;
   };
 
   SMLoc StartLoc, EndLoc;
 
-  /// Internal constructor for register kinds
-  static MipsOperand *CreateReg(unsigned Index, RegKind RegKind,
-                                const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
-                                MipsAsmParser &Parser) {
-    MipsOperand *Op = new MipsOperand(k_RegisterIndex, Parser);
-    Op->RegIdx.Index = Index;
-    Op->RegIdx.RegInfo = RegInfo;
-    Op->RegIdx.Kind = RegKind;
-    Op->StartLoc = S;
-    Op->EndLoc = E;
-    return Op;
-  }
-
 public:
-  /// Coerce the register to GPR32 and return the real register for the current
-  /// target.
-  unsigned getGPR32Reg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
-    AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
-    unsigned ClassID = Mips::GPR32RegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to GPR64 and return the real register for the current
-  /// target.
-  unsigned getGPR64Reg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
-    unsigned ClassID = Mips::GPR64RegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+  void addRegOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::CreateReg(getReg()));
   }
 
-private:
-  /// Coerce the register to AFGR64 and return the real register for the current
-  /// target.
-  unsigned getAFGR64Reg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
-    if (RegIdx.Index % 2 != 0)
-      AsmParser.Warning(StartLoc, "Float register should be even.");
-    return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
-        .getRegister(RegIdx.Index / 2);
-  }
-
-  /// Coerce the register to FGR64 and return the real register for the current
-  /// target.
-  unsigned getFGR64Reg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
-    return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
-        .getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to FGR32 and return the real register for the current
-  /// target.
-  unsigned getFGR32Reg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
-    return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
-        .getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to FGRH32 and return the real register for the current
-  /// target.
-  unsigned getFGRH32Reg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
-    return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
-        .getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to FCC and return the real register for the current
-  /// target.
-  unsigned getFCCReg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
-    return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
-        .getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to MSA128 and return the real register for the current
-  /// target.
-  unsigned getMSA128Reg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
-    // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
-    // identical
-    unsigned ClassID = Mips::MSA128BRegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to MSACtrl and return the real register for the
-  /// current target.
-  unsigned getMSACtrlReg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
-    unsigned ClassID = Mips::MSACtrlRegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to COP2 and return the real register for the
-  /// current target.
-  unsigned getCOP2Reg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
-    unsigned ClassID = Mips::COP2RegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to ACC64DSP and return the real register for the
-  /// current target.
-  unsigned getACC64DSPReg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
-    unsigned ClassID = Mips::ACC64DSPRegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to HI32DSP and return the real register for the
-  /// current target.
-  unsigned getHI32DSPReg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
-    unsigned ClassID = Mips::HI32DSPRegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to LO32DSP and return the real register for the
-  /// current target.
-  unsigned getLO32DSPReg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
-    unsigned ClassID = Mips::LO32DSPRegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to CCR and return the real register for the
-  /// current target.
-  unsigned getCCRReg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
-    unsigned ClassID = Mips::CCRRegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
-  }
-
-  /// Coerce the register to HWRegs and return the real register for the
-  /// current target.
-  unsigned getHWRegsReg() const {
-    assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
-    unsigned ClassID = Mips::HWRegsRegClassID;
-    return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+  void addPtrRegOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::CreateReg(getPtrReg()));
   }
 
-public:
   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
     // Add as immediate when possible.  Null MCExpr = 0.
     if (Expr == 0)
@@ -473,85 +397,6 @@ public:
       Inst.addOperand(MCOperand::CreateExpr(Expr));
   }
 
-  void addRegOperands(MCInst &Inst, unsigned N) const {
-    llvm_unreachable("Use a custom parser instead");
-  }
-
-  void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
-  }
-
-  void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
-  }
-
-  void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
-  }
-
-  void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
-  }
-
-  void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
-  }
-
-  void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
-  }
-
-  void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
-  }
-
-  void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
-  }
-
-  void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
-  }
-
-  void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
-  }
-
-  void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
-  }
-
-  void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
-  }
-
-  void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
-  }
-
-  void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
-  }
-
-  void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
-  }
-
   void addImmOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     const MCExpr *Expr = getImm();
@@ -561,38 +406,19 @@ public:
   void addMemOperands(MCInst &Inst, unsigned N) const {
     assert(N == 2 && "Invalid number of operands!");
 
-    Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
+    Inst.addOperand(MCOperand::CreateReg(getMemBase()));
 
     const MCExpr *Expr = getMemOff();
     addExpr(Inst, Expr);
   }
 
-  bool isReg() const {
-    // As a special case until we sort out the definition of div/divu, pretend
-    // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
-    if (isGPRAsmReg() && RegIdx.Index == 0)
-      return true;
-
-    return Kind == k_PhysRegister;
-  }
-  bool isRegIdx() const { return Kind == k_RegisterIndex; }
+  bool isReg() const { return Kind == k_Register; }
   bool isImm() const { return Kind == k_Immediate; }
-  bool isConstantImm() const {
-    return isImm() && dyn_cast<MCConstantExpr>(getImm());
-  }
-  bool isToken() const {
-    // Note: It's not possible to pretend that other operand kinds are tokens.
-    // The matcher emitter checks tokens first.
-    return Kind == k_Token;
-  }
+  bool isToken() const { return Kind == k_Token; }
   bool isMem() const { return Kind == k_Memory; }
+  bool isPtrReg() const { return Kind == k_PtrReg; }
   bool isInvNum() const { return Kind == k_Immediate; }
-  bool isLSAImm() const {
-    if (!isConstantImm())
-      return false;
-    int64_t Val = getConstantImm();
-    return 1 <= Val && Val <= 4;
-  }
+  bool isLSAImm() const { return Kind == k_LSAImm; }
 
   StringRef getToken() const {
     assert(Kind == k_Token && "Invalid access!");
@@ -600,27 +426,26 @@ public:
   }
 
   unsigned getReg() const {
-    // As a special case until we sort out the definition of div/divu, pretend
-    // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
-    if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
-        RegIdx.Kind & RegKind_GPR)
-      return getGPR32Reg(); // FIXME: GPR64 too
+    assert((Kind == k_Register) && "Invalid access!");
+    return Reg.RegNum;
+  }
 
-    assert(Kind == k_PhysRegister && "Invalid access!");
-    return PhysReg.Num;
+  unsigned getPtrReg() const {
+    assert((Kind == k_PtrReg) && "Invalid access!");
+    return Reg.RegNum;
   }
 
-  const MCExpr *getImm() const {
-    assert((Kind == k_Immediate) && "Invalid access!");
-    return Imm.Val;
+  void setRegKind(RegisterKind RegKind) {
+    assert((Kind == k_Register || Kind == k_PtrReg) && "Invalid access!");
+    Reg.Kind = RegKind;
   }
 
-  int64_t getConstantImm() const {
-    const MCExpr *Val = getImm();
-    return static_cast<const MCConstantExpr *>(Val)->getValue();
+  const MCExpr *getImm() const {
+    assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!");
+    return Imm.Val;
   }
 
-  MipsOperand *getMemBase() const {
+  unsigned getMemBase() const {
     assert((Kind == k_Memory) && "Invalid access!");
     return Mem.Base;
   }
@@ -630,9 +455,8 @@ public:
     return Mem.Off;
   }
 
-  static MipsOperand *CreateToken(StringRef Str, SMLoc S,
-                                  MipsAsmParser &Parser) {
-    MipsOperand *Op = new MipsOperand(k_Token, Parser);
+  static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
+    MipsOperand *Op = new MipsOperand(k_Token);
     Op->Tok.Data = Str.data();
     Op->Tok.Length = Str.size();
     Op->StartLoc = S;
@@ -640,75 +464,43 @@ public:
     return Op;
   }
 
-  /// Create a numeric register (e.g. $1). The exact register remains
-  /// unresolved until an instruction successfully matches
-  static MipsOperand *CreateNumericReg(unsigned Index,
-                                       const MCRegisterInfo *RegInfo, SMLoc S,
-                                       SMLoc E, MipsAsmParser &Parser) {
-    DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
-    return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
-  }
-
-  /// Create a register that is definitely a GPR.
-  /// This is typically only used for named registers such as $gp.
-  static MipsOperand *CreateGPRReg(unsigned Index,
-                                   const MCRegisterInfo *RegInfo, SMLoc S,
-                                   SMLoc E, MipsAsmParser &Parser) {
-    return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
-  }
-
-  /// Create a register that is definitely a FGR.
-  /// This is typically only used for named registers such as $f0.
-  static MipsOperand *CreateFGRReg(unsigned Index,
-                                   const MCRegisterInfo *RegInfo, SMLoc S,
-                                   SMLoc E, MipsAsmParser &Parser) {
-    return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
-  }
-
-  /// Create a register that is definitely an FCC.
-  /// This is typically only used for named registers such as $fcc0.
-  static MipsOperand *CreateFCCReg(unsigned Index,
-                                   const MCRegisterInfo *RegInfo, SMLoc S,
-                                   SMLoc E, MipsAsmParser &Parser) {
-    return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
-  }
-
-  /// Create a register that is definitely an ACC.
-  /// This is typically only used for named registers such as $ac0.
-  static MipsOperand *CreateACCReg(unsigned Index,
-                                   const MCRegisterInfo *RegInfo, SMLoc S,
-                                   SMLoc E, MipsAsmParser &Parser) {
-    return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
+  static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
+    MipsOperand *Op = new MipsOperand(k_Register);
+    Op->Reg.RegNum = RegNum;
+    Op->Reg.Kind = Kind_None;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
   }
 
-  /// Create a register that is definitely an MSA128.
-  /// This is typically only used for named registers such as $w0.
-  static MipsOperand *CreateMSA128Reg(unsigned Index,
-                                      const MCRegisterInfo *RegInfo, SMLoc S,
-                                      SMLoc E, MipsAsmParser &Parser) {
-    return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
+  static MipsOperand *CreatePtrReg(unsigned RegNum, SMLoc S, SMLoc E) {
+    MipsOperand *Op = new MipsOperand(k_PtrReg);
+    Op->Reg.RegNum = RegNum;
+    Op->Reg.Kind = Kind_None;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
   }
 
-  /// Create a register that is definitely an MSACtrl.
-  /// This is typically only used for named registers such as $msaaccess.
-  static MipsOperand *CreateMSACtrlReg(unsigned Index,
-                                       const MCRegisterInfo *RegInfo, SMLoc S,
-                                       SMLoc E, MipsAsmParser &Parser) {
-    return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
+  static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
+    MipsOperand *Op = new MipsOperand(k_Immediate);
+    Op->Imm.Val = Val;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
   }
 
-  static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E,
-                                MipsAsmParser &Parser) {
-    MipsOperand *Op = new MipsOperand(k_Immediate, Parser);
+  static MipsOperand *CreateLSAImm(const MCExpr *Val, SMLoc S, SMLoc E) {
+    MipsOperand *Op = new MipsOperand(k_LSAImm);
     Op->Imm.Val = Val;
     Op->StartLoc = S;
     Op->EndLoc = E;
     return Op;
   }
 
-  static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S,
-                                SMLoc E, MipsAsmParser &Parser) {
-    MipsOperand *Op = new MipsOperand(k_Memory, Parser);
+  static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
+                                SMLoc E) {
+    MipsOperand *Op = new MipsOperand(k_Memory);
     Op->Mem.Base = Base;
     Op->Mem.Off = Off;
     Op->StartLoc = S;
@@ -716,33 +508,79 @@ public:
     return Op;
   }
 
-  bool isGPRAsmReg() const {
-    return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
+  bool isGPR32Asm() const {
+    return Kind == k_Register && Reg.Kind == Kind_GPR32;
+  }
+  void addRegAsmOperands(MCInst &Inst, unsigned N) const {
+    Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
+  }
+
+  bool isGPR64Asm() const {
+    return Kind == k_Register && Reg.Kind == Kind_GPR64;
+  }
+
+  bool isHWRegsAsm() const {
+    assert((Kind == k_Register) && "Invalid access!");
+    return Reg.Kind == Kind_HWRegs;
+  }
+
+  bool isCCRAsm() const {
+    assert((Kind == k_Register) && "Invalid access!");
+    return Reg.Kind == Kind_CCRRegs;
+  }
+
+  bool isAFGR64Asm() const {
+    return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
+  }
+
+  bool isFGR64Asm() const {
+    return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
+  }
+
+  bool isFGR32Asm() const {
+    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 isFGRAsmReg() const {
-    // AFGR64 is $0-$15 but we handle this in getAFGR64()
-    return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
+
+  bool isACC64DSPAsm() const {
+    return Kind == k_Register && Reg.Kind == Kind_ACC64DSP;
   }
-  bool isHWRegsAsmReg() const {
-    return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
+
+  bool isLO32DSPAsm() const {
+    return Kind == k_Register && Reg.Kind == Kind_LO32DSP;
   }
-  bool isCCRAsmReg() const {
-    return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
+
+  bool isHI32DSPAsm() const {
+    return Kind == k_Register && Reg.Kind == Kind_HI32DSP;
   }
-  bool isFCCAsmReg() const {
-    return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7;
+
+  bool isCOP2Asm() const { return Kind == k_Register && Reg.Kind == Kind_COP2; }
+
+  bool isMSA128BAsm() const {
+    return Kind == k_Register && Reg.Kind == Kind_MSA128BRegs;
   }
-  bool isACCAsmReg() const {
-    return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
+
+  bool isMSA128HAsm() const {
+    return Kind == k_Register && Reg.Kind == Kind_MSA128HRegs;
   }
-  bool isCOP2AsmReg() const {
-    return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
+
+  bool isMSA128WAsm() const {
+    return Kind == k_Register && Reg.Kind == Kind_MSA128WRegs;
   }
-  bool isMSA128AsmReg() const {
-    return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
+
+  bool isMSA128DAsm() const {
+    return Kind == k_Register && Reg.Kind == Kind_MSA128DRegs;
   }
-  bool isMSACtrlAsmReg() const {
-    return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
+
+  bool isMSA128CRAsm() const {
+    return Kind == k_Register && Reg.Kind == Kind_MSA128CtrlRegs;
   }
 
   /// getStartLoc - Get the location of the first token of this operand.
@@ -751,29 +589,7 @@ public:
   SMLoc getEndLoc() const { return EndLoc; }
 
   virtual void print(raw_ostream &OS) const {
-    switch (Kind) {
-    case k_Immediate:
-      OS << "Imm<";
-      Imm.Val->print(OS);
-      OS << ">";
-      break;
-    case k_Memory:
-      OS << "Mem<";
-      Mem.Base->print(OS);
-      OS << ", ";
-      Mem.Off->print(OS);
-      OS << ">";
-      break;
-    case k_PhysRegister:
-      OS << "PhysReg<" << PhysReg.Num << ">";
-      break;
-    case k_RegisterIndex:
-      OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
-      break;
-    case k_Token:
-      OS << Tok.Data;
-      break;
-    }
+    llvm_unreachable("unimplemented!");
   }
 }; // class MipsOperand
 } // namespace
@@ -800,8 +616,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
       break;
     case Mips::BEQ:
     case Mips::BNE:
-    case Mips::BEQ_MM:
-    case Mips::BNE_MM:
       assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
       Offset = Inst.getOperand(2);
       if (!Offset.isImm())
@@ -819,14 +633,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
     case Mips::BLTZAL:
     case Mips::BC1F:
     case Mips::BC1T:
-    case Mips::BGEZ_MM:
-    case Mips::BGTZ_MM:
-    case Mips::BLEZ_MM:
-    case Mips::BLTZ_MM:
-    case Mips::BGEZAL_MM:
-    case Mips::BLTZAL_MM:
-    case Mips::BC1F_MM:
-    case Mips::BC1T_MM:
       assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
       Offset = Inst.getOperand(1);
       if (!Offset.isImm())
@@ -1190,13 +996,14 @@ bool MipsAsmParser::MatchAndEmitInstruction(
   return true;
 }
 
-void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
-  if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
-    if (RegIndex == 1)
-      Warning(Loc, "Used $at without \".set noat\"");
+void MipsAsmParser::warnIfAssemblerTemporary(int RegNo) {
+  if ((RegNo != 0) && ((int)Options.getATRegNum() == RegNo)) {
+    if (RegNo == 1)
+      Warning(getLexer().getLoc(), "Used $at without \".set noat\"");
     else
-      Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
-                       Twine(RegIndex) + "\"");
+      Warning(getLexer().getLoc(), Twine("Used $") + Twine(RegNo) +
+                                       " with \".set at=$" + Twine(RegNo) +
+                                       "\"");
   }
 }
 
@@ -1257,6 +1064,8 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) {
                .Default(-1);
   }
 
+  warnIfAssemblerTemporary(CC);
+
   return CC;
 }
 
@@ -1331,6 +1140,59 @@ int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
   return CC;
 }
 
+int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
+
+  int CC;
+  CC = matchCPURegisterName(Name);
+  if (CC != -1)
+    return matchRegisterByNumber(CC, is64BitReg ? Mips::GPR64RegClassID
+                                                : Mips::GPR32RegClassID);
+  CC = matchFPURegisterName(Name);
+  // TODO: decide about fpu register class
+  if (CC != -1)
+    return matchRegisterByNumber(CC, isFP64() ? Mips::FGR64RegClassID
+                                              : Mips::FGR32RegClassID);
+  return matchMSA128RegisterName(Name);
+}
+
+int MipsAsmParser::regKindToRegClass(int RegKind) {
+
+  switch (RegKind) {
+  case MipsOperand::Kind_GPR32:
+    return Mips::GPR32RegClassID;
+  case MipsOperand::Kind_GPR64:
+    return Mips::GPR64RegClassID;
+  case MipsOperand::Kind_HWRegs:
+    return Mips::HWRegsRegClassID;
+  case MipsOperand::Kind_FGR32Regs:
+    return Mips::FGR32RegClassID;
+  case MipsOperand::Kind_FGRH32Regs:
+    return Mips::FGRH32RegClassID;
+  case MipsOperand::Kind_FGR64Regs:
+    return Mips::FGR64RegClassID;
+  case MipsOperand::Kind_AFGR64Regs:
+    return Mips::AFGR64RegClassID;
+  case MipsOperand::Kind_CCRRegs:
+    return Mips::CCRRegClassID;
+  case MipsOperand::Kind_ACC64DSP:
+    return Mips::ACC64DSPRegClassID;
+  case MipsOperand::Kind_FCCRegs:
+    return Mips::FCCRegClassID;
+  case MipsOperand::Kind_MSA128BRegs:
+    return Mips::MSA128BRegClassID;
+  case MipsOperand::Kind_MSA128HRegs:
+    return Mips::MSA128HRegClassID;
+  case MipsOperand::Kind_MSA128WRegs:
+    return Mips::MSA128WRegClassID;
+  case MipsOperand::Kind_MSA128DRegs:
+    return Mips::MSA128DRegClassID;
+  case MipsOperand::Kind_MSA128CtrlRegs:
+    return Mips::MSACtrlRegClassID;
+  default:
+    return -1;
+  }
+}
+
 bool MipsAssemblerOptions::setATReg(unsigned Reg) {
   if (Reg > 31)
     return false;
@@ -1360,14 +1222,45 @@ int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
       getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
     return -1;
 
+  if (RegClass == Mips::GPR32RegClassID || RegClass == Mips::GPR64RegClassID)
+    warnIfAssemblerTemporary(RegNum);
+
   return getReg(RegClass, RegNum);
 }
 
+int MipsAsmParser::tryParseRegister(bool is64BitReg) {
+  const AsmToken &Tok = Parser.getTok();
+  int RegNum = -1;
+
+  if (Tok.is(AsmToken::Identifier)) {
+    std::string lowerCase = Tok.getString().lower();
+    RegNum = matchRegisterName(lowerCase, is64BitReg);
+  } else if (Tok.is(AsmToken::Integer))
+    RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
+                                   is64BitReg ? Mips::GPR64RegClassID
+                                              : Mips::GPR32RegClassID);
+  return RegNum;
+}
+
+bool MipsAsmParser::tryParseRegisterOperand(
+    SmallVectorImpl<MCParsedAsmOperand *> &Operands, bool is64BitReg) {
+
+  SMLoc S = Parser.getTok().getLoc();
+  int RegNo = -1;
+
+  RegNo = tryParseRegister(is64BitReg);
+  if (RegNo == -1)
+    return true;
+
+  Operands.push_back(
+      MipsOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
+  Parser.Lex(); // Eat register token.
+  return false;
+}
+
 bool
 MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
                             StringRef Mnemonic) {
-  DEBUG(dbgs() << "ParseOperand\n");
-
   // Check if the current operand has a custom associated parser, if so, try to
   // custom parse the operand, or fallback to the general approach.
   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
@@ -1379,8 +1272,6 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
   if (ResTy == MatchOperand_ParseFail)
     return true;
 
-  DEBUG(dbgs() << ".. Generic Parser\n");
-
   switch (getLexer().getKind()) {
   default:
     Error(Parser.getTok().getLoc(), "unexpected token in operand");
@@ -1388,15 +1279,29 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
   case AsmToken::Dollar: {
     // Parse the register.
     SMLoc S = Parser.getTok().getLoc();
+    Parser.Lex(); // Eat dollar token.
+    // Parse the register operand.
+    if (!tryParseRegisterOperand(Operands, isGP64())) {
+      if (getLexer().is(AsmToken::LParen)) {
+        // Check if it is indexed addressing operand.
+        Operands.push_back(MipsOperand::CreateToken("(", S));
+        Parser.Lex(); // Eat the parenthesis.
+        if (getLexer().isNot(AsmToken::Dollar))
+          return true;
 
-    // Almost all registers have been parsed by custom parsers. There is only
-    // one exception to this. $zero (and it's alias $0) will reach this point
-    // for div, divu, and similar instructions because it is not an operand
-    // to the instruction definition but an explicit register. Special case
-    // this situation for now.
-    if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
-      return false;
+        Parser.Lex(); // Eat the dollar
+        if (tryParseRegisterOperand(Operands, isGP64()))
+          return true;
+
+        if (!getLexer().is(AsmToken::RParen))
+          return true;
 
+        S = Parser.getTok().getLoc();
+        Operands.push_back(MipsOperand::CreateToken(")", S));
+        Parser.Lex();
+      }
+      return false;
+    }
     // Maybe it is a symbol reference.
     StringRef Identifier;
     if (Parser.parseIdentifier(Identifier))
@@ -1408,18 +1313,47 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
     const MCExpr *Res =
         MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
 
-    Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
+    Operands.push_back(MipsOperand::CreateImm(Res, S, E));
     return false;
   }
+  case AsmToken::Identifier:
+    // For instruction aliases like "bc1f $Label" dedicated parser will
+    // eat the '$' sign before failing. So in order to look for appropriate
+    // label we must check first if we have already consumed '$'.
+    if (hasConsumedDollar) {
+      hasConsumedDollar = false;
+      SMLoc S = Parser.getTok().getLoc();
+      StringRef Identifier;
+      if (Parser.parseIdentifier(Identifier))
+        return true;
+      SMLoc E =
+          SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+      MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
+      // Create a symbol reference.
+      const MCExpr *Res =
+          MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
+
+      Operands.push_back(MipsOperand::CreateImm(Res, S, E));
+      return false;
+    }
+    // Look for the existing symbol, we should check if
+    // we need to assign the proper RegisterKind.
+    if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
+      return false;
   // Else drop to expression parsing.
   case AsmToken::LParen:
   case AsmToken::Minus:
   case AsmToken::Plus:
   case AsmToken::Integer:
   case AsmToken::String: {
-    DEBUG(dbgs() << ".. generic integer\n");
-    OperandMatchResultTy ResTy = ParseImm(Operands);
-    return ResTy != MatchOperand_Success;
+    // Quoted label names.
+    const MCExpr *IdVal;
+    SMLoc S = Parser.getTok().getLoc();
+    if (getParser().parseExpression(IdVal))
+      return true;
+    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
+    return false;
   }
   case AsmToken::Percent: {
     // It is a symbol reference or constant expression.
@@ -1430,7 +1364,7 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
 
     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
 
-    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
+    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
     return false;
   } // case AsmToken::Percent
   } // switch(getLexer().getKind())
@@ -1562,27 +1496,9 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
 
 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
                                   SMLoc &EndLoc) {
-  SmallVector<MCParsedAsmOperand *, 1> Operands;
-  OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
-  if (ResTy == MatchOperand_Success) {
-    assert(Operands.size() == 1);
-    MipsOperand &Operand = *static_cast<MipsOperand *>(Operands.front());
-    StartLoc = Operand.getStartLoc();
-    EndLoc = Operand.getEndLoc();
-
-    // AFAIK, we only support numeric registers and named GPR's in CFI
-    // directives.
-    // Don't worry about eating tokens before failing. Using an unrecognised
-    // register is a parse error.
-    if (Operand.isGPRAsmReg()) {
-      // Resolve to GPR32 or GPR64 appropriately.
-      RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
-    }
-
-    return (RegNo == (unsigned)-1);
-  }
-
-  assert(Operands.size() == 0);
+  StartLoc = Parser.getTok().getLoc();
+  RegNo = tryParseRegister(isGP64());
+  EndLoc = Parser.getTok().getLoc();
   return (RegNo == (unsigned)-1);
 }
 
@@ -1616,7 +1532,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
 
 MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
     SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-  DEBUG(dbgs() << "parseMemOperand\n");
+
   const MCExpr *IdVal = 0;
   SMLoc S;
   bool isParenExpr = false;
@@ -1639,7 +1555,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
       if (Mnemonic->getToken() == "la") {
         SMLoc E =
             SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
-        Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
+        Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
         return MatchOperand_Success;
       }
       if (Tok.is(AsmToken::EndOfStatement)) {
@@ -1647,9 +1563,8 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
             SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
 
         // Zero register assumed, add a memory operand with ZERO as its base.
-        MipsOperand *Base = MipsOperand::CreateGPRReg(
-            0, getContext().getRegisterInfo(), S, E, *this);
-        Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
+        Operands.push_back(MipsOperand::CreateMem(
+            isGP64() ? Mips::ZERO_64 : Mips::ZERO, IdVal, S, E));
         return MatchOperand_Success;
       }
       Error(Parser.getTok().getLoc(), "'(' expected");
@@ -1659,7 +1574,8 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
     Parser.Lex(); // Eat the '(' token.
   }
 
-  Res = ParseAnyRegister(Operands);
+  Res = parseRegs(Operands, isGP64() ? (int)MipsOperand::Kind_GPR64
+                                     : (int)MipsOperand::Kind_GPR32);
   if (Res != MatchOperand_Success)
     return Res;
 
@@ -1677,6 +1593,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
 
   // Replace the register operand with the memory operand.
   MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
+  int RegNo = op->getReg();
   // Remove the register from the operands.
   Operands.pop_back();
   // Add the memory operand.
@@ -1689,220 +1606,599 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
                                    getContext());
   }
 
-  Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this));
+  Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
+  delete op;
   return MatchOperand_Success;
 }
 
-bool MipsAsmParser::searchSymbolAlias(
-    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+bool MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+                                int RegKind) {
+  // If the first token is not '$' we have an error.
+  if (Parser.getTok().isNot(AsmToken::Dollar))
+    return false;
 
-  MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
-  if (Sym) {
-    SMLoc S = Parser.getTok().getLoc();
-    const MCExpr *Expr;
-    if (Sym->isVariable())
-      Expr = Sym->getVariableValue();
-    else
+  SMLoc S = Parser.getTok().getLoc();
+  Parser.Lex();
+  AsmToken::TokenKind TkKind = getLexer().getKind();
+  int Reg;
+
+  if (TkKind == AsmToken::Integer) {
+    Reg = matchRegisterByNumber(Parser.getTok().getIntVal(),
+                                regKindToRegClass(RegKind));
+    if (Reg == -1)
       return false;
-    if (Expr->getKind() == MCExpr::SymbolRef) {
-      const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
-      const StringRef DefSymbol = Ref->getSymbol().getName();
-      if (DefSymbol.startswith("$")) {
-        OperandMatchResultTy ResTy =
-            MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
-        if (ResTy == MatchOperand_Success)
-          return true;
-        else if (ResTy == MatchOperand_ParseFail)
-          llvm_unreachable("Should never ParseFail");
-        return false;
-      }
-    } else if (Expr->getKind() == MCExpr::Constant) {
-      Parser.Lex();
-      const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
-      MipsOperand *op =
-          MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this);
-      Operands.push_back(op);
-      return true;
-    }
+  } else if (TkKind == AsmToken::Identifier) {
+    if ((Reg = matchCPURegisterName(Parser.getTok().getString().lower())) == -1)
+      return false;
+    Reg = getReg(regKindToRegClass(RegKind), Reg);
+  } else {
+    return false;
   }
-  return false;
+
+  MipsOperand *Op = MipsOperand::CreatePtrReg(Reg, S, Parser.getTok().getLoc());
+  Op->setRegKind((MipsOperand::RegisterKind)RegKind);
+  Operands.push_back(Op);
+  Parser.Lex();
+  return true;
 }
 
 MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::MatchAnyRegisterNameWithoutDollar(
-    SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
-    SMLoc S) {
-  int Index = matchCPURegisterName(Identifier);
-  if (Index != -1) {
-    Parser.Lex();
-    Operands.push_back(MipsOperand::CreateGPRReg(
-        Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
-    return MatchOperand_Success;
-  }
+MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  MipsOperand::RegisterKind RegKind =
+      isN64() ? MipsOperand::Kind_GPR64 : MipsOperand::Kind_GPR32;
 
-  Index = matchFPURegisterName(Identifier);
-  if (Index != -1) {
-    Parser.Lex();
-    Operands.push_back(MipsOperand::CreateFGRReg(
-        Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
+  // Parse index register.
+  if (!parsePtrReg(Operands, RegKind))
+    return MatchOperand_NoMatch;
+
+  // Parse '('.
+  if (Parser.getTok().isNot(AsmToken::LParen))
+    return MatchOperand_NoMatch;
+
+  Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
+  Parser.Lex();
+
+  // Parse base register.
+  if (!parsePtrReg(Operands, RegKind))
+    return MatchOperand_NoMatch;
+
+  // Parse ')'.
+  if (Parser.getTok().isNot(AsmToken::RParen))
+    return MatchOperand_NoMatch;
+
+  Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
+  Parser.Lex();
+
+  return MatchOperand_Success;
+}
+
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+                         int RegKind) {
+  MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
+  if (getLexer().getKind() == AsmToken::Identifier && !hasConsumedDollar) {
+    if (searchSymbolAlias(Operands, Kind))
+      return MatchOperand_Success;
+    return MatchOperand_NoMatch;
+  }
+  SMLoc S = Parser.getTok().getLoc();
+  // If the first token is not '$', we have an error.
+  if (Parser.getTok().isNot(AsmToken::Dollar) && !hasConsumedDollar)
+    return MatchOperand_NoMatch;
+  if (!hasConsumedDollar) {
+    Parser.Lex(); // Eat the '$'
+    hasConsumedDollar = true;
+  }
+  if (getLexer().getKind() == AsmToken::Identifier) {
+    int RegNum = -1;
+    std::string RegName = Parser.getTok().getString().lower();
+    // Match register by name
+    switch (RegKind) {
+    case MipsOperand::Kind_GPR32:
+    case MipsOperand::Kind_GPR64:
+      RegNum = matchCPURegisterName(RegName);
+      break;
+    case MipsOperand::Kind_AFGR64Regs:
+    case MipsOperand::Kind_FGR64Regs:
+    case MipsOperand::Kind_FGR32Regs:
+    case MipsOperand::Kind_FGRH32Regs:
+      RegNum = matchFPURegisterName(RegName);
+      if (RegKind == MipsOperand::Kind_AFGR64Regs)
+        RegNum /= 2;
+      else if (RegKind == MipsOperand::Kind_FGRH32Regs && !isFP64())
+        if (RegNum != -1 && RegNum % 2 != 0)
+          Warning(S, "Float register should be even.");
+      break;
+    case MipsOperand::Kind_FCCRegs:
+      RegNum = matchFCCRegisterName(RegName);
+      break;
+    case MipsOperand::Kind_ACC64DSP:
+      RegNum = matchACRegisterName(RegName);
+      break;
+    default:
+      break; // No match, value is set to -1.
+    }
+    // No match found, return _NoMatch to give a chance to other round.
+    if (RegNum < 0)
+      return MatchOperand_NoMatch;
+
+    int RegVal = getReg(regKindToRegClass(Kind), RegNum);
+    if (RegVal == -1)
+      return MatchOperand_NoMatch;
+
+    MipsOperand *Op =
+        MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
+    Op->setRegKind(Kind);
+    Operands.push_back(Op);
+    hasConsumedDollar = false;
+    Parser.Lex(); // Eat the register name.
+    return MatchOperand_Success;
+  } else if (getLexer().getKind() == AsmToken::Integer) {
+    unsigned RegNum = Parser.getTok().getIntVal();
+    if (Kind == MipsOperand::Kind_HWRegs) {
+      if (RegNum != 29)
+        return MatchOperand_NoMatch;
+      // Only hwreg 29 is supported, found at index 0.
+      RegNum = 0;
+    }
+    int Reg = matchRegisterByNumber(RegNum, regKindToRegClass(Kind));
+    if (Reg == -1)
+      return MatchOperand_NoMatch;
+    MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
+    Op->setRegKind(Kind);
+    Operands.push_back(Op);
+    hasConsumedDollar = false;
+    Parser.Lex(); // Eat the register number.
+    if ((RegKind == MipsOperand::Kind_GPR32) &&
+        (getLexer().is(AsmToken::LParen))) {
+      // Check if it is indexed addressing operand.
+      Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
+      Parser.Lex(); // Eat the parenthesis.
+      if (parseRegs(Operands, RegKind) != MatchOperand_Success)
+        return MatchOperand_NoMatch;
+      if (getLexer().isNot(AsmToken::RParen))
+        return MatchOperand_NoMatch;
+      Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
+      Parser.Lex();
+    }
     return MatchOperand_Success;
   }
+  return MatchOperand_NoMatch;
+}
 
-  Index = matchFCCRegisterName(Identifier);
-  if (Index != -1) {
-    Parser.Lex();
-    Operands.push_back(MipsOperand::CreateFCCReg(
-        Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
-    return MatchOperand_Success;
+bool MipsAsmParser::validateMSAIndex(int Val, int RegKind) {
+  MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
+
+  if (Val < 0)
+    return false;
+
+  switch (Kind) {
+  default:
+    return false;
+  case MipsOperand::Kind_MSA128BRegs:
+    return Val < 16;
+  case MipsOperand::Kind_MSA128HRegs:
+    return Val < 8;
+  case MipsOperand::Kind_MSA128WRegs:
+    return Val < 4;
+  case MipsOperand::Kind_MSA128DRegs:
+    return Val < 2;
   }
+}
 
-  Index = matchACRegisterName(Identifier);
-  if (Index != -1) {
-    Parser.Lex();
-    Operands.push_back(MipsOperand::CreateACCReg(
-        Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
-    return MatchOperand_Success;
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+                            int RegKind) {
+  MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
+  SMLoc S = Parser.getTok().getLoc();
+  std::string RegName;
+
+  if (Parser.getTok().isNot(AsmToken::Dollar))
+    return MatchOperand_NoMatch;
+
+  switch (RegKind) {
+  default:
+    return MatchOperand_ParseFail;
+  case MipsOperand::Kind_MSA128BRegs:
+  case MipsOperand::Kind_MSA128HRegs:
+  case MipsOperand::Kind_MSA128WRegs:
+  case MipsOperand::Kind_MSA128DRegs:
+    break;
   }
 
-  Index = matchMSA128RegisterName(Identifier);
-  if (Index != -1) {
-    Parser.Lex();
-    Operands.push_back(MipsOperand::CreateMSA128Reg(
-        Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
+  Parser.Lex(); // Eat the '$'.
+  if (getLexer().getKind() == AsmToken::Identifier)
+    RegName = Parser.getTok().getString().lower();
+  else
+    return MatchOperand_ParseFail;
+
+  int RegNum = matchMSA128RegisterName(RegName);
+
+  if (RegNum < 0 || RegNum > 31)
+    return MatchOperand_ParseFail;
+
+  int RegVal = getReg(regKindToRegClass(Kind), RegNum);
+  if (RegVal == -1)
+    return MatchOperand_ParseFail;
+
+  MipsOperand *Op = MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
+  Op->setRegKind(Kind);
+  Operands.push_back(Op);
+
+  Parser.Lex(); // Eat the register identifier.
+
+  // MSA registers may be suffixed with an index in the form of:
+  // 1) Immediate expression.
+  // 2) General Purpose Register.
+  // Examples:
+  //   1) copy_s.b $29,$w0[0]
+  //   2) sld.b $w0,$w1[$1]
+
+  if (Parser.getTok().isNot(AsmToken::LBrac))
     return MatchOperand_Success;
-  }
 
-  Index = matchMSA128CtrlRegisterName(Identifier);
-  if (Index != -1) {
-    Parser.Lex();
-    Operands.push_back(MipsOperand::CreateMSACtrlReg(
-        Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
+  MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
+
+  Operands.push_back(MipsOperand::CreateToken("[", Parser.getTok().getLoc()));
+  Parser.Lex(); // Parse the '[' token.
+
+  if (Parser.getTok().is(AsmToken::Dollar)) {
+    // This must be a GPR.
+    MipsOperand *RegOp;
+    SMLoc VIdx = Parser.getTok().getLoc();
+    Parser.Lex(); // Parse the '$' token.
+
+    // GPR have aliases and we must account for that. Example: $30 == $fp
+    if (getLexer().getKind() == AsmToken::Integer) {
+      unsigned RegNum = Parser.getTok().getIntVal();
+      int Reg = matchRegisterByNumber(
+          RegNum, regKindToRegClass(MipsOperand::Kind_GPR32));
+      if (Reg == -1) {
+        Error(VIdx, "invalid general purpose register");
+        return MatchOperand_ParseFail;
+      }
+
+      RegOp = MipsOperand::CreateReg(Reg, VIdx, Parser.getTok().getLoc());
+    } else if (getLexer().getKind() == AsmToken::Identifier) {
+      int RegNum = -1;
+      std::string RegName = Parser.getTok().getString().lower();
+
+      RegNum = matchCPURegisterName(RegName);
+      if (RegNum == -1) {
+        Error(VIdx, "general purpose register expected");
+        return MatchOperand_ParseFail;
+      }
+      RegNum = getReg(regKindToRegClass(MipsOperand::Kind_GPR32), RegNum);
+      RegOp = MipsOperand::CreateReg(RegNum, VIdx, Parser.getTok().getLoc());
+    } else
+      return MatchOperand_ParseFail;
+
+    RegOp->setRegKind(MipsOperand::Kind_GPR32);
+    Operands.push_back(RegOp);
+    Parser.Lex(); // Eat the register identifier.
+
+    if (Parser.getTok().isNot(AsmToken::RBrac))
+      return MatchOperand_ParseFail;
+
+    Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
+    Parser.Lex(); // Parse the ']' token.
+
     return MatchOperand_Success;
   }
 
-  return MatchOperand_NoMatch;
+  // 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::ParseAnyRegisterWithoutDollar(
-    SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc S) {
-  auto Token = Parser.getTok();
-
-  if (Token.is(AsmToken::Identifier)) {
-    DEBUG(dbgs() << ".. identifier\n");
-    StringRef Identifier = Token.getIdentifier();
-    return MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
-  } else if (Token.is(AsmToken::Integer)) {
-    DEBUG(dbgs() << ".. integer\n");
-    Operands.push_back(MipsOperand::CreateNumericReg(
-        Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
-        *this));
-    Parser.Lex();
-    return MatchOperand_Success;
-  }
+MipsAsmParser::parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+                                int RegKind) {
+  MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
+
+  if (Kind != MipsOperand::Kind_MSA128CtrlRegs)
+    return MatchOperand_NoMatch;
 
-  DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
+  if (Parser.getTok().isNot(AsmToken::Dollar))
+    return MatchOperand_ParseFail;
 
-  return MatchOperand_NoMatch;
+  SMLoc S = Parser.getTok().getLoc();
+
+  Parser.Lex(); // Eat the '$' symbol.
+
+  int RegNum = -1;
+  if (getLexer().getKind() == AsmToken::Identifier)
+    RegNum = matchMSA128CtrlRegisterName(Parser.getTok().getString().lower());
+  else if (getLexer().getKind() == AsmToken::Integer)
+    RegNum = Parser.getTok().getIntVal();
+  else
+    return MatchOperand_ParseFail;
+
+  if (RegNum < 0 || RegNum > 7)
+    return MatchOperand_ParseFail;
+
+  int RegVal = getReg(regKindToRegClass(Kind), RegNum);
+  if (RegVal == -1)
+    return MatchOperand_ParseFail;
+
+  MipsOperand *RegOp =
+      MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
+  RegOp->setRegKind(MipsOperand::Kind_MSA128CtrlRegs);
+  Operands.push_back(RegOp);
+  Parser.Lex(); // Eat the register identifier.
+
+  return MatchOperand_Success;
 }
 
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
-    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-  DEBUG(dbgs() << "ParseAnyRegister\n");
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+
+  if (!isGP64())
+    return MatchOperand_NoMatch;
+  return parseRegs(Operands, (int)MipsOperand::Kind_GPR64);
+}
+
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseRegs(Operands, (int)MipsOperand::Kind_GPR32);
+}
 
-  auto Token = Parser.getTok();
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAFGR64Regs(
+    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
 
-  SMLoc S = Token.getLoc();
+  if (isFP64())
+    return MatchOperand_NoMatch;
+  return parseRegs(Operands, (int)MipsOperand::Kind_AFGR64Regs);
+}
 
-  if (Token.isNot(AsmToken::Dollar)) {
-    DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
-    if (Token.is(AsmToken::Identifier)) {
-      if (searchSymbolAlias(Operands))
-        return MatchOperand_Success;
-    }
-    DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  if (!isFP64())
     return MatchOperand_NoMatch;
-  }
-  DEBUG(dbgs() << ".. $\n");
-  Parser.Lex();
-  Token = Parser.getTok();
+  return parseRegs(Operands, (int)MipsOperand::Kind_FGR64Regs);
+}
+
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseRegs(Operands, (int)MipsOperand::Kind_FGR32Regs);
+}
 
-  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::parseFGRH32Regs(
+    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseRegs(Operands, (int)MipsOperand::Kind_FGRH32Regs);
 }
 
 MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-  switch (getLexer().getKind()) {
-  default:
+MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseRegs(Operands, (int)MipsOperand::Kind_FCCRegs);
+}
+
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseRegs(Operands, (int)MipsOperand::Kind_ACC64DSP);
+}
+
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  // If the first token is not '$' we have an error.
+  if (Parser.getTok().isNot(AsmToken::Dollar))
     return MatchOperand_NoMatch;
-  case AsmToken::LParen:
-  case AsmToken::Minus:
-  case AsmToken::Plus:
-  case AsmToken::Integer:
-  case AsmToken::String:
-    break;
-  }
 
-  const MCExpr *IdVal;
   SMLoc S = Parser.getTok().getLoc();
-  if (getParser().parseExpression(IdVal))
-    return MatchOperand_ParseFail;
+  Parser.Lex(); // Eat the '$'
 
-  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
-  Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
+  const AsmToken &Tok = Parser.getTok(); // Get next token.
+
+  if (Tok.isNot(AsmToken::Identifier))
+    return MatchOperand_NoMatch;
+
+  if (!Tok.getIdentifier().startswith("ac"))
+    return MatchOperand_NoMatch;
+
+  StringRef NumString = Tok.getIdentifier().substr(2);
+
+  unsigned IntVal;
+  if (NumString.getAsInteger(10, IntVal))
+    return MatchOperand_NoMatch;
+
+  unsigned Reg = matchRegisterByNumber(IntVal, Mips::LO32DSPRegClassID);
+
+  MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
+  Op->setRegKind(MipsOperand::Kind_LO32DSP);
+  Operands.push_back(Op);
+
+  Parser.Lex(); // Eat the register number.
   return MatchOperand_Success;
 }
 
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
-    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-  DEBUG(dbgs() << "ParseJumpTarget\n");
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  // If the first token is not '$' we have an error.
+  if (Parser.getTok().isNot(AsmToken::Dollar))
+    return MatchOperand_NoMatch;
 
-  SMLoc S = getLexer().getLoc();
+  SMLoc S = Parser.getTok().getLoc();
+  Parser.Lex(); // Eat the '$'
 
-  // Integers and expressions are acceptable
-  OperandMatchResultTy ResTy = ParseImm(Operands);
-  if (ResTy != MatchOperand_NoMatch)
-    return ResTy;
+  const AsmToken &Tok = Parser.getTok(); // Get next token.
 
-  // Consume the $ if there is one. We'll add it to the symbol below.
-  bool hasConsumedDollar = false;
-  if (getLexer().is(AsmToken::Dollar)) {
-    Parser.Lex();
-    hasConsumedDollar = true;
+  if (Tok.isNot(AsmToken::Identifier))
+    return MatchOperand_NoMatch;
 
-    // We have an unfortunate conflict between '$sym' and '$reg' so give
-    // registers a chance before we try symbols.
-    // The conflict is between 'bc1t $offset', and 'bc1t $fcc, $offset'.
-    OperandMatchResultTy ResTy = ParseAnyRegisterWithoutDollar(Operands, S);
-    if (ResTy != MatchOperand_NoMatch)
-      return ResTy;
-  }
+  if (!Tok.getIdentifier().startswith("ac"))
+    return MatchOperand_NoMatch;
 
-  StringRef Identifier;
-  if (Parser.parseIdentifier(Identifier))
-    return hasConsumedDollar ? MatchOperand_ParseFail : MatchOperand_NoMatch;
+  StringRef NumString = Tok.getIdentifier().substr(2);
 
-  if (hasConsumedDollar)
-    Identifier = StringRef("$" + Identifier.str());
+  unsigned IntVal;
+  if (NumString.getAsInteger(10, IntVal))
+    return MatchOperand_NoMatch;
 
-  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
-  MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
+  unsigned Reg = matchRegisterByNumber(IntVal, Mips::HI32DSPRegClassID);
 
-  // Create a symbol reference.
-  const MCExpr *Res =
-      MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
+  MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
+  Op->setRegKind(MipsOperand::Kind_HI32DSP);
+  Operands.push_back(Op);
 
-  Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
+  Parser.Lex(); // Eat the register number.
   return MatchOperand_Success;
-  //  // Look for the existing symbol, we should check if
-  //  // we need to assign the proper RegisterKind.
-  //  if (searchSymbolAlias(Operands))
-  //    return false;
+}
 
-  return MatchOperand_NoMatch;
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  // If the first token is not '$' we have an error.
+  if (Parser.getTok().isNot(AsmToken::Dollar))
+    return MatchOperand_NoMatch;
+
+  SMLoc S = Parser.getTok().getLoc();
+  Parser.Lex(); // Eat the '$'
+
+  const AsmToken &Tok = Parser.getTok(); // Get next token.
+
+  if (Tok.isNot(AsmToken::Integer))
+    return MatchOperand_NoMatch;
+
+  unsigned IntVal = Tok.getIntVal();
+
+  unsigned Reg = matchRegisterByNumber(IntVal, Mips::COP2RegClassID);
+
+  MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
+  Op->setRegKind(MipsOperand::Kind_COP2);
+  Operands.push_back(Op);
+
+  Parser.Lex(); // Eat the register number.
+  return MatchOperand_Success;
+}
+
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128BRegs(
+    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128BRegs);
+}
+
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128HRegs(
+    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128HRegs);
+}
+
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128WRegs(
+    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128WRegs);
+}
+
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128DRegs(
+    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128DRegs);
+}
+
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128CtrlRegs(
+    SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseMSACtrlRegs(Operands, (int)MipsOperand::Kind_MSA128CtrlRegs);
+}
+
+bool MipsAsmParser::searchSymbolAlias(
+    SmallVectorImpl<MCParsedAsmOperand *> &Operands, unsigned RegKind) {
+
+  MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
+  if (Sym) {
+    SMLoc S = Parser.getTok().getLoc();
+    const MCExpr *Expr;
+    if (Sym->isVariable())
+      Expr = Sym->getVariableValue();
+    else
+      return false;
+    if (Expr->getKind() == MCExpr::SymbolRef) {
+      MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
+      const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
+      const StringRef DefSymbol = Ref->getSymbol().getName();
+      if (DefSymbol.startswith("$")) {
+        int RegNum = -1;
+        APInt IntVal(32, -1);
+        if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
+          RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
+                                         isGP64() ? Mips::GPR64RegClassID
+                                                  : Mips::GPR32RegClassID);
+        else {
+          // Lookup for the register with the corresponding name.
+          switch (Kind) {
+          case MipsOperand::Kind_AFGR64Regs:
+          case MipsOperand::Kind_FGR64Regs:
+            RegNum = matchFPURegisterName(DefSymbol.substr(1));
+            break;
+          case MipsOperand::Kind_FGR32Regs:
+            RegNum = matchFPURegisterName(DefSymbol.substr(1));
+            break;
+          case MipsOperand::Kind_GPR64:
+          case MipsOperand::Kind_GPR32:
+          default:
+            RegNum = matchCPURegisterName(DefSymbol.substr(1));
+            break;
+          }
+          if (RegNum > -1)
+            RegNum = getReg(regKindToRegClass(Kind), RegNum);
+        }
+        if (RegNum > -1) {
+          Parser.Lex();
+          MipsOperand *op =
+              MipsOperand::CreateReg(RegNum, S, Parser.getTok().getLoc());
+          op->setRegKind(Kind);
+          Operands.push_back(op);
+          return true;
+        }
+      }
+    } else if (Expr->getKind() == MCExpr::Constant) {
+      Parser.Lex();
+      const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
+      MipsOperand *op =
+          MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc());
+      Operands.push_back(op);
+      return true;
+    }
+  }
+  return false;
+}
+
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseRegs(Operands, (int)MipsOperand::Kind_HWRegs);
+}
+
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+  return parseRegs(Operands, (int)MipsOperand::Kind_CCRRegs);
 }
 
 MipsAsmParser::OperandMatchResultTy
@@ -1919,12 +2215,12 @@ MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
   int64_t Val = MCE->getValue();
   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
   Operands.push_back(MipsOperand::CreateImm(
-      MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
+      MCConstantExpr::Create(0 - Val, getContext()), S, E));
   return MatchOperand_Success;
 }
 
 MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
   switch (getLexer().getKind()) {
   default:
     return MatchOperand_NoMatch;
@@ -1958,7 +2254,7 @@ MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
   }
 
   Operands.push_back(
-      MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
+      MipsOperand::CreateLSAImm(Expr, S, Parser.getTok().getLoc()));
   return MatchOperand_Success;
 }
 
@@ -1996,74 +2292,16 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
   return VK;
 }
 
-/// Sometimes (i.e. load/stores) the operand may be followed immediately by
-/// either this.
-/// ::= '(', register, ')'
-/// handle it before we iterate so we don't get tripped up by the lack of
-/// a comma.
-bool MipsAsmParser::ParseParenSuffix(
-    StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-  if (getLexer().is(AsmToken::LParen)) {
-    Operands.push_back(
-        MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
-    Parser.Lex();
-    if (ParseOperand(Operands, Name)) {
-      SMLoc Loc = getLexer().getLoc();
-      Parser.eatToEndOfStatement();
-      return Error(Loc, "unexpected token in argument list");
-    }
-    if (Parser.getTok().isNot(AsmToken::RParen)) {
-      SMLoc Loc = getLexer().getLoc();
-      Parser.eatToEndOfStatement();
-      return Error(Loc, "unexpected token, expected ')'");
-    }
-    Operands.push_back(
-        MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
-    Parser.Lex();
-  }
-  return false;
-}
-
-/// Sometimes (i.e. in MSA) the operand may be followed immediately by
-/// either one of these.
-/// ::= '[', register, ']'
-/// ::= '[', integer, ']'
-/// handle it before we iterate so we don't get tripped up by the lack of
-/// a comma.
-bool MipsAsmParser::ParseBracketSuffix(
-    StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-  if (getLexer().is(AsmToken::LBrac)) {
-    Operands.push_back(
-        MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
-    Parser.Lex();
-    if (ParseOperand(Operands, Name)) {
-      SMLoc Loc = getLexer().getLoc();
-      Parser.eatToEndOfStatement();
-      return Error(Loc, "unexpected token in argument list");
-    }
-    if (Parser.getTok().isNot(AsmToken::RBrac)) {
-      SMLoc Loc = getLexer().getLoc();
-      Parser.eatToEndOfStatement();
-      return Error(Loc, "unexpected token, expected ']'");
-    }
-    Operands.push_back(
-        MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
-    Parser.Lex();
-  }
-  return false;
-}
-
 bool MipsAsmParser::ParseInstruction(
     ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
     SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-  DEBUG(dbgs() << "ParseInstruction\n");
   // Check if we have valid mnemonic
   if (!mnemonicIsValid(Name, 0)) {
     Parser.eatToEndOfStatement();
     return Error(NameLoc, "Unknown instruction");
   }
   // First operand in MCInst is instruction mnemonic.
-  Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
+  Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
 
   // Read the remaining operands.
   if (getLexer().isNot(AsmToken::EndOfStatement)) {
@@ -2073,9 +2311,6 @@ bool MipsAsmParser::ParseInstruction(
       Parser.eatToEndOfStatement();
       return Error(Loc, "unexpected token in argument list");
     }
-    if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
-      return true;
-    // AFAIK, parenthesis suffixes are never on the first operand
 
     while (getLexer().is(AsmToken::Comma)) {
       Parser.Lex(); // Eat the comma.
@@ -2085,13 +2320,6 @@ bool MipsAsmParser::ParseInstruction(
         Parser.eatToEndOfStatement();
         return Error(Loc, "unexpected token in argument list");
       }
-      // Parse bracket and parenthesis suffixes before we iterate
-      if (getLexer().is(AsmToken::LBrac)) {
-        if (ParseBracketSuffix(Name, Operands))
-          return true;
-      } else if (getLexer().is(AsmToken::LParen) &&
-                 ParseParenSuffix(Name, Operands))
-        return true;
     }
   }
   if (getLexer().isNot(AsmToken::EndOfStatement)) {
index fc3b922602c20d9b576f16164b2ef41987248e43..a543840132367e2824792d6c8e48e1dcab52b4ce 100644 (file)
@@ -263,11 +263,6 @@ 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 <typename InsnType>
-static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address,
-                                   const void *Decoder);
 namespace llvm {
 extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
               TheMips64elTarget;
@@ -309,53 +304,8 @@ extern "C" void LLVMInitializeMipsDisassembler() {
                                          createMips64elDisassembler);
 }
 
-#include "MipsGenDisassemblerTables.inc"
-
-template <typename InsnType>
-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;
-}
+#include "MipsGenDisassemblerTables.inc"
 
   /// readInstruction - read four bytes from the MemoryObject
   /// and return 32 bit word sorted according to the given endianess
index abf36daab416edaabf46fd296bac288aafe84839..04520b7a221130b4d7b8df18bf98e1f0f345d128 100644 (file)
@@ -197,7 +197,6 @@ 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;
   }
 }
index 35dd39617fb25c3e701c0d72405d5b7895de7d50..5a105ffc893080f969cc2474b786eb01f5f4c41d 100644 (file)
@@ -184,9 +184,6 @@ 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,
 
index 71d0a18d48c97cbc86fa21f52a0868855edc3613..af4fa6410c8fde858204095cc0e1f71cf9741af9 100644 (file)
@@ -236,27 +236,17 @@ 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<OtherVT> {
   let EncoderMethod = "getJumpTargetOpValue";
-  let ParserMatchClass = MipsJumpTargetAsmOperand;
 }
 def brtarget    : Operand<OtherVT> {
   let EncoderMethod = "getBranchTargetOpValue";
   let OperandType = "OPERAND_PCREL";
   let DecoderMethod = "DecodeBranchTarget";
-  let ParserMatchClass = MipsJumpTargetAsmOperand;
 }
 def calltarget  : Operand<iPTR> {
   let EncoderMethod = "getJumpTargetOpValue";
-  let ParserMatchClass = MipsJumpTargetAsmOperand;
 }
 
 def simm10 : Operand<i32>;
@@ -278,11 +268,6 @@ def simm16_64   : Operand<i64> {
   let DecoderMethod = "DecodeSimm16";
 }
 
-// Zero
-def uimmz       : Operand<i32> {
-  let PrintMethod = "printUnsignedImm";
-}
-
 // Unsigned Operand
 def uimm5       : Operand<i32> {
   let PrintMethod = "printUnsignedImm";
@@ -310,6 +295,12 @@ def MipsInvertedImmoperand : AsmOperandClass {
   let ParserMethod = "parseInvNum";
 }
 
+def PtrRegAsmOperand : AsmOperandClass {
+  let Name = "PtrReg";
+  let ParserMethod = "parsePtrReg";
+}
+
+
 def InvertedImOperand : Operand<i32> {
   let ParserMatchClass = MipsInvertedImmoperand;
 }
@@ -341,7 +332,7 @@ def mem_ea : Operand<iPTR> {
 def PtrRC : Operand<iPTR> {
   let MIOperandInfo = (ops ptr_rc);
   let DecoderMethod = "DecodePtrRegisterClass";
-  let ParserMatchClass = GPR32AsmOperand;
+  let ParserMatchClass = PtrRegAsmOperand;
 }
 
 // size operand of ext instruction
@@ -369,9 +360,6 @@ def HI16 : SDNodeXForm<imm, [{
 // Plus 1.
 def Plus1 : SDNodeXForm<imm, [{ return getImm(N, N->getSExtValue() + 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()); }]>;
index 5722c6cf00b33d5625aa764d1ed6a342eb093a5d..4a30d5ae9698b9812d4ccf1334a93644aafed59f 100644 (file)
@@ -27,9 +27,6 @@ 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>;
@@ -53,7 +50,6 @@ 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>;
@@ -73,7 +69,7 @@ def uimm2 : Operand<i32> {
 // as the encoded value should be subtracted by one.
 def uimm2LSAAsmOperand : AsmOperandClass {
   let Name = "LSAImm";
-  let ParserMethod = "ParseLSAImm";
+  let ParserMethod = "parseLSAImm";
   let RenderMethod = "addImmOperands";
 }
 
@@ -160,15 +156,6 @@ 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<ValueType ResTy, ValueType OpTy, CondCode CC> :
   PatFrag<(ops node:$lhs, node:$rhs),
           (ResTy (vfsetcc (OpTy node:$lhs), (OpTy node:$rhs), CC))>;
@@ -1415,9 +1402,9 @@ class MSA_3R_SPLAT_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
                              RegisterOperand ROWD, RegisterOperand ROWS = ROWD,
                              InstrItinClass itin = NoItinerary> {
   dag OutOperandList = (outs ROWD:$wd);
-  dag InOperandList = (ins ROWS:$ws, GPR32Opnd:$rt);
+  dag InOperandList = (ins ROWS:$ws, GPR32:$rt);
   string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$rt]");
-  list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, GPR32Opnd:$rt))];
+  list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, GPR32:$rt))];
   InstrItinClass Itinerary = itin;
 }
 
@@ -1438,10 +1425,10 @@ class MSA_3R_SLD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
                            RegisterOperand ROWD, RegisterOperand ROWS = ROWD,
                            InstrItinClass itin = NoItinerary> {
   dag OutOperandList = (outs ROWD:$wd);
-  dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, GPR32Opnd:$rt);
+  dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, GPR32:$rt);
   string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$rt]");
   list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROWS:$ws,
-                                              GPR32Opnd:$rt))];
+                                              GPR32:$rt))];
   InstrItinClass Itinerary = itin;
   string Constraints = "$wd = $wd_in";
 }
@@ -1509,12 +1496,11 @@ class MSA_INSVE_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
                           RegisterOperand ROWD, RegisterOperand ROWS = ROWD,
                           InstrItinClass itin = NoItinerary> {
   dag OutOperandList = (outs ROWD:$wd);
-  dag InOperandList = (ins ROWD:$wd_in, uimm6:$n, ROWS:$ws, uimmz:$n2);
-  string AsmString = !strconcat(instr_asm, "\t$wd[$n], $ws[$n2]");
+  dag InOperandList = (ins ROWD:$wd_in, uimm6:$n, ROWS:$ws);
+  string AsmString = !strconcat(instr_asm, "\t$wd[$n], $ws[0]");
   list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in,
                                               immZExt6:$n,
-                                              ROWS:$ws,
-                                              immz:$n2))];
+                                              ROWS:$ws))];
   InstrItinClass Itinerary = itin;
   string Constraints = "$wd = $wd_in";
 }
@@ -2305,13 +2291,13 @@ class INSERT_FW_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v4f32,
 class INSERT_FD_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v2f64,
                                                      MSA128DOpnd, FGR64Opnd>;
 
-class INSVE_B_DESC : MSA_INSVE_DESC_BASE<"insve.b", insve_v16i8,
+class INSVE_B_DESC : MSA_INSVE_DESC_BASE<"insve.b", int_mips_insve_b,
                                          MSA128BOpnd>;
-class INSVE_H_DESC : MSA_INSVE_DESC_BASE<"insve.h", insve_v8i16,
+class INSVE_H_DESC : MSA_INSVE_DESC_BASE<"insve.h", int_mips_insve_h,
                                          MSA128HOpnd>;
-class INSVE_W_DESC : MSA_INSVE_DESC_BASE<"insve.w", insve_v4i32,
+class INSVE_W_DESC : MSA_INSVE_DESC_BASE<"insve.w", int_mips_insve_w,
                                          MSA128WOpnd>;
-class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", insve_v2i64,
+class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", int_mips_insve_d,
                                          MSA128DOpnd>;
 
 class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
@@ -3202,14 +3188,10 @@ def INSERT_D : INSERT_D_ENC, INSERT_D_DESC;
 // INSERT_FW_PSEUDO defined after INSVE_W
 // INSERT_FD_PSEUDO defined after INSVE_D
 
-// There is a fourth operand that is not present in the encoding. Use a
-// custom decoder to get a chance to add it.
-let DecoderMethod = "DecodeINSVE_DF" in {
-  def INSVE_B : INSVE_B_ENC, INSVE_B_DESC;
-  def INSVE_H : INSVE_H_ENC, INSVE_H_DESC;
-  def INSVE_W : INSVE_W_ENC, INSVE_W_DESC;
-  def INSVE_D : INSVE_D_ENC, INSVE_D_DESC;
-}
+def INSVE_B : INSVE_B_ENC, INSVE_B_DESC;
+def INSVE_H : INSVE_H_ENC, INSVE_H_DESC;
+def INSVE_W : INSVE_W_ENC, INSVE_W_DESC;
+def INSVE_D : INSVE_D_ENC, INSVE_D_DESC;
 
 def INSERT_FW_PSEUDO : INSERT_FW_PSEUDO_DESC;
 def INSERT_FD_PSEUDO : INSERT_FD_PSEUDO_DESC;
index 834e6c5fc7bbbc4b3f85261a172a60785641a2f6..f5e0bf5f00b5596d8ea3ebacb74fb0de6a453e2c 100644 (file)
@@ -209,8 +209,7 @@ let Namespace = "Mips" in {
   def PC : Register<"pc">;
 
   // Hardware register $29
-  foreach I = 0-31 in
-  def HWR#I : MipsReg<#I, ""#I>;
+  def HWR29 : MipsReg<29, "29">;
 
   // Accum registers
   foreach I = 0-3 in
@@ -365,8 +364,7 @@ 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, (sequence "HWR%u", 0, 31)>,
-             Unallocatable;
+def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>, Unallocatable;
 
 // Accumulator Registers
 def ACC64 : RegisterClass<"Mips", [untyped], 64, (add AC0)> {
@@ -396,68 +394,86 @@ def OCTEON_P : RegisterClass<"Mips", [i64], 64, (add P0, P1, P2)>,
 // Register Operands.
 
 class MipsAsmRegOperand : AsmOperandClass {
-  let ParserMethod = "ParseAnyRegister";
+  let RenderMethod = "addRegAsmOperands";
 }
-
-def GPR64AsmOperand : MipsAsmRegOperand {
-  let Name = "GPR64AsmReg";
-  let PredicateMethod = "isGPRAsmReg";
+def GPR32AsmOperand : MipsAsmRegOperand {
+  let Name = "GPR32Asm";
+  let ParserMethod = "parseGPR32";
 }
 
-def GPR32AsmOperand : MipsAsmRegOperand {
-  let Name = "GPR32AsmReg";
-  let PredicateMethod = "isGPRAsmReg";
+def GPR64AsmOperand : MipsAsmRegOperand {
+  let Name = "GPR64Asm";
+  let ParserMethod = "parseGPR64";
 }
 
 def ACC64DSPAsmOperand : MipsAsmRegOperand {
-  let Name = "ACC64DSPAsmReg";
-  let PredicateMethod = "isACCAsmReg";
+  let Name = "ACC64DSPAsm";
+  let ParserMethod = "parseACC64DSP";
 }
 
-def HI32DSPAsmOperand : MipsAsmRegOperand {
-  let Name = "HI32DSPAsmReg";
-  let PredicateMethod = "isACCAsmReg";
+def LO32DSPAsmOperand : MipsAsmRegOperand {
+  let Name = "LO32DSPAsm";
+  let ParserMethod = "parseLO32DSP";
 }
 
-def LO32DSPAsmOperand : MipsAsmRegOperand {
-  let Name = "LO32DSPAsmReg";
-  let PredicateMethod = "isACCAsmReg";
+def HI32DSPAsmOperand : MipsAsmRegOperand {
+  let Name = "HI32DSPAsm";
+  let ParserMethod = "parseHI32DSP";
 }
 
 def CCRAsmOperand : MipsAsmRegOperand {
-  let Name = "CCRAsmReg";
+  let Name = "CCRAsm";
+  let ParserMethod = "parseCCRRegs";
 }
 
 def AFGR64AsmOperand : MipsAsmRegOperand {
-  let Name = "AFGR64AsmReg";
-  let PredicateMethod = "isFGRAsmReg";
+  let Name = "AFGR64Asm";
+  let ParserMethod = "parseAFGR64Regs";
 }
 
 def FGR64AsmOperand : MipsAsmRegOperand {
-  let Name = "FGR64AsmReg";
-  let PredicateMethod = "isFGRAsmReg";
+  let Name = "FGR64Asm";
+  let ParserMethod = "parseFGR64Regs";
 }
 
 def FGR32AsmOperand : MipsAsmRegOperand {
-  let Name = "FGR32AsmReg";
-  let PredicateMethod = "isFGRAsmReg";
+  let Name = "FGR32Asm";
+  let ParserMethod = "parseFGR32Regs";
 }
 
 def FGRH32AsmOperand : MipsAsmRegOperand {
-  let Name = "FGRH32AsmReg";
-  let PredicateMethod = "isFGRAsmReg";
+  let Name = "FGRH32Asm";
+  let ParserMethod = "parseFGRH32Regs";
 }
 
 def FCCRegsAsmOperand : MipsAsmRegOperand {
-  let Name = "FCCAsmReg";
+  let Name = "FCCRegsAsm";
+  let ParserMethod = "parseFCCRegs";
+}
+
+def MSA128BAsmOperand : MipsAsmRegOperand {
+  let Name = "MSA128BAsm";
+  let ParserMethod = "parseMSA128BRegs";
+}
+
+def MSA128HAsmOperand : MipsAsmRegOperand {
+  let Name = "MSA128HAsm";
+  let ParserMethod = "parseMSA128HRegs";
+}
+
+def MSA128WAsmOperand : MipsAsmRegOperand {
+  let Name = "MSA128WAsm";
+  let ParserMethod = "parseMSA128WRegs";
 }
 
-def MSA128AsmOperand : MipsAsmRegOperand {
-  let Name = "MSA128AsmReg";
+def MSA128DAsmOperand : MipsAsmRegOperand {
+  let Name = "MSA128DAsm";
+  let ParserMethod = "parseMSA128DRegs";
 }
 
-def MSACtrlAsmOperand : MipsAsmRegOperand {
-  let Name = "MSACtrlAsmReg";
+def MSA128CRAsmOperand : MipsAsmRegOperand {
+  let Name = "MSA128CRAsm";
+  let ParserMethod = "parseMSA128CtrlRegs";
 }
 
 def GPR32Opnd : RegisterOperand<GPR32> {
@@ -477,11 +493,13 @@ def CCROpnd : RegisterOperand<CCR> {
 }
 
 def HWRegsAsmOperand : MipsAsmRegOperand {
-  let Name = "HWRegsAsmReg";
+  let Name = "HWRegsAsm";
+  let ParserMethod = "parseHWRegs";
 }
 
 def COP2AsmOperand : MipsAsmRegOperand {
-  let Name = "COP2AsmReg";
+  let Name = "COP2Asm";
+  let ParserMethod = "parseCOP2";
 }
 
 def HWRegsOpnd : RegisterOperand<HWRegs> {
@@ -525,22 +543,22 @@ def COP2Opnd : RegisterOperand<COP2> {
 }
 
 def MSA128BOpnd : RegisterOperand<MSA128B> {
-  let ParserMatchClass = MSA128AsmOperand;
+  let ParserMatchClass = MSA128BAsmOperand;
 }
 
 def MSA128HOpnd : RegisterOperand<MSA128H> {
-  let ParserMatchClass = MSA128AsmOperand;
+  let ParserMatchClass = MSA128HAsmOperand;
 }
 
 def MSA128WOpnd : RegisterOperand<MSA128W> {
-  let ParserMatchClass = MSA128AsmOperand;
+  let ParserMatchClass = MSA128WAsmOperand;
 }
 
 def MSA128DOpnd : RegisterOperand<MSA128D> {
-  let ParserMatchClass = MSA128AsmOperand;
+  let ParserMatchClass = MSA128DAsmOperand;
 }
 
 def MSA128CROpnd : RegisterOperand<MSACtrl> {
-  let ParserMatchClass = MSACtrlAsmOperand;
+  let ParserMatchClass = MSA128CRAsmOperand;
 }
 
index 0dac0b79909d835aa1abe1d2778b507af0540544..218cd15baa9737a74f5932154ad27e8d4136a68a 100644 (file)
@@ -1810,13 +1810,6 @@ 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:
@@ -2844,8 +2837,7 @@ MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI,
   BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_W), Wd)
       .addReg(Wd_in)
       .addImm(Lane)
-      .addReg(Wt)
-      .addImm(0);
+      .addReg(Wt);
 
   MI->eraseFromParent(); // The pseudo instruction is gone now.
   return BB;
@@ -2878,8 +2870,7 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI,
   BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_D), Wd)
       .addReg(Wd_in)
       .addImm(Lane)
-      .addReg(Wt)
-      .addImm(0);
+      .addReg(Wt);
 
   MI->eraseFromParent(); // The pseudo instruction is gone now.
   return BB;
diff --git a/test/MC/Mips/cfi.s b/test/MC/Mips/cfi.s
deleted file mode 100644 (file)
index a3247b5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# 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
index e6f8416a41ebf1741525f090f86bf7cbcc1ea908..df1054fed426fb09f6984ecce706cd9523c1602f 100644 (file)
@@ -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]]:17: error: invalid operand for instruction
+# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
         add     $32, $0, $0
index 7f802ef765f967d936edb77d6b58e68f9fe195e3..dd4e482f38125b31367440a720cfcaa3802f9f61 100644 (file)
@@ -8,6 +8,10 @@
 # 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
index 703d49a4ea756835ca3632f5077fdc4938a783b9..f5c98f0007e78aeea1d77f69f6353a7e8f8b5f1b 100644 (file)
        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
index 5dbb1d3b4970e359562fd71451ea843c6072668d..dff3ae43f1e7c093baad3a9993a137202bc633f3 100644 (file)
@@ -2,7 +2,7 @@
 # they aren't implemented yet).
 # This test is set up to XPASS if any instruction generates an encoding.
 #
-# RUN: not llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r2 | not FileCheck %s
+# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r2 | FileCheck %s
 # CHECK-NOT: encoding
 # XFAIL: *
 
@@ -48,6 +48,7 @@
        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
@@ -65,6 +66,7 @@
        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
        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
        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
        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
        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
        swe     $t8,94($k0)
        swle    $v1,-209($gp)
        swre    $k0,-202($s2)
+       swxc1   $f19,$t4($k0)
        synci   20023($s0)
        tlbginv
        tlbginvf
index 29c0807fff1ad58882b3bf36c315eb3834de631d..03f51554250775f1958cfa8919a56a834c59ad67 100644 (file)
        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
        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)
        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)
        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
index 26749a91532d9aefc7510e56fa8ba6158faf95d3..7599164af0b1648ddd256436b849169a946540b4 100644 (file)
        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
index bcc9f689bfab29f1801c3a63ae93df0f4e082262..66886c5794e2786f44456cf39befe68dd319dcd7 100644 (file)
        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
index 285aabbfe6b6b78ce3ee563abb8d07f3075a6397..10931587e458008d1761fc7e7f242daa9e52a5ab 100644 (file)
        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
index 64c2ff5e789eaf1cb06efa88010146597fe843fd..7665d1f025e9075d17f21fb1ece84b26a538c89f 100644 (file)
        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
index 66f15e03c24b5cb06f4d01781bd10c1af7b565b1..11ed7747b24f85e89897458d17613f4939ea5843 100644 (file)
        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
index 673754535bc08ae4b32366a46c8ee5cce727f4f2..cfd708ce6672a3bfe3b69653476d1e6b095f7a99 100644 (file)
        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
index 3e725ea96832a41f51731b0b6045cb9db540cfc5..7279707ea0b558c68ddfb1facfa96762f7ca8de1 100644 (file)
@@ -5,6 +5,7 @@
 # RUN: not llvm-mc %s -triple=mips64-unknown-linux -show-encoding -mcpu=mips64r2 | not FileCheck %s
 # CHECK-NOT: encoding
 # XFAIL: *
+# REQUIRES: asserts
 
        .set noat
        abs.ps  $f22,$f8
@@ -51,6 +52,7 @@
        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
@@ -68,6 +70,7 @@
        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
        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
        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
        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
        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
        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
        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
        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
        tlbwi
        tlbwr
        wrpgpr  $zero,$t5
+       wsbh    $k1,$t1
        xor.v   $w20,$w21,$w30
        yield   $v1,$s0
index 4e549af9e79e0325ffe6a581830582cb57b84630..e1d80199c34762cec0ede4a4c3e18ce7393fe4fc 100644 (file)
        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
        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
@@ -87,7 +79,6 @@
        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
        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
        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
        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
        trunc.w.d       $f22,$f15
        trunc.w.s       $f28,$f30
        xor     $s2,$a0,$s8
-       wsbh    $k1,$t1
index 1bd26ffa855de7f37a2c8f0faede589202df4bcc..71f1a98fae49e2cfb3106caba01a39500eeda0fa 100644 (file)
@@ -7,12 +7,12 @@
     .text
 foo:
 # CHECK:   jr    $1                      # encoding: [0x08,0x00,0x20,0x00]
-# WARNINGS: :[[@LINE+2]]:11: warning: Used $at without ".set noat"
+# WARNINGS: :[[@LINE+2]]:12: warning: Used $at without ".set noat"
     .set    at=$1
     jr    $at
 
 # CHECK:   jr    $1                      # encoding: [0x08,0x00,0x20,0x00]
-# WARNINGS: :[[@LINE+2]]:11: warning: Used $at without ".set noat"
+# WARNINGS: :[[@LINE+2]]:12: 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]]:11: warning: Used $16 with ".set at=$16"
+# WARNINGS: :[[@LINE+2]]:12: warning: Used $16 with ".set at=$16"
     .set    at=$16
     jr    $s0
 
 # CHECK:   jr    $16                     # encoding: [0x08,0x00,0x00,0x02]
-# WARNINGS: :[[@LINE+2]]:11: warning: Used $16 with ".set at=$16"
+# WARNINGS: :[[@LINE+2]]:12: warning: Used $16 with ".set at=$16"
     .set    at=$16
     jr    $16
 # WARNINGS-NOT: warning