summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Sanders <daniel.sanders@imgtec.com>2014-04-01 10:35:28 +0000
committerDaniel Sanders <daniel.sanders@imgtec.com>2014-04-01 10:35:28 +0000
commitbd48d31b37cbde04b51daec14139f7f10fdf4878 (patch)
tree055c427117ff408f8356bda96a1ebd757ebcd84d
parenta5b283ab2319688fe8a64aa3798c8453184ce8e4 (diff)
downloadllvm-bd48d31b37cbde04b51daec14139f7f10fdf4878.tar.gz
llvm-bd48d31b37cbde04b51daec14139f7f10fdf4878.tar.bz2
llvm-bd48d31b37cbde04b51daec14139f7f10fdf4878.tar.xz
[mips] Rewrite MipsAsmParser and MipsOperand.
Summary: Highlights: - Registers are resolved much later (by the render method). Prior to that point, GPR32's/GPR64's are GPR's regardless of register size. Similarly FGR32's/FGR64's/AFGR64's are FGR's regardless of register size or FR mode. Numeric registers can be anything. - All registers are parsed the same way everywhere (even when handling symbol aliasing) - One consequence is that all registers can be specified numerically almost anywhere (e.g. $fccX, $wX). The exception is symbol aliasing but that can be easily resolved. - Removes the need for the hasConsumedDollar hack - Parenthesis and Bracket suffixes are handled generically - Micromips instructions are parsed directly instead of going through the standard encodings first. - rdhwr accepts all 32 registers, and the following instructions that previously xfailed now work: ddiv, ddivu, div, divu, cvt.l.[ds], se[bh], wsbh, floor.w.[ds], c.ngl.d, c.sf.s, dsbh, dshd, madd.s, msub.s, nmadd.s, nmsub.s, swxc1 - Diagnostics involving registers point at the correct character (the $) - There's only one kind of immediate in MipsOperand. LSA immediates are handled by the predicate and renderer. Lowlights: - Hardcoded '$zero' in the div patterns is handled with a hack. MipsOperand::isReg() will return true for a k_RegisterIndex token with Index == 0 and getReg() will return ZERO for this case. Note that it doesn't return ZERO_64 on isGP64() targets. - I haven't cleaned up all of the now-unused functions. Some more of the generic parser could be removed too (integers and relocs for example). - insve.df needed a custom decoder to handle the implicit fourth operand that was needed to make it parse correctly. The difficulty was that the matcher expected a Token<'0'> but gets an Imm<0>. Adding an implicit zero solved this. Reviewers: matheusalmeida, vmedic Reviewed By: matheusalmeida Differential Revision: http://llvm-reviews.chandlerc.com/D3222 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205292 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp1636
-rw-r--r--lib/Target/Mips/Disassembler/MipsDisassembler.cpp52
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp1
-rw-r--r--lib/Target/Mips/MipsISelLowering.h3
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td26
-rw-r--r--lib/Target/Mips/MipsMSAInstrInfo.td50
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.td100
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.cpp13
-rw-r--r--test/MC/Mips/cfi.s13
-rw-r--r--test/MC/Mips/mips-register-names-invalid.s2
-rw-r--r--test/MC/Mips/mips3/valid-xfail.s4
-rw-r--r--test/MC/Mips/mips3/valid.s4
-rw-r--r--test/MC/Mips/mips32r2/valid-xfail.s16
-rw-r--r--test/MC/Mips/mips32r2/valid.s14
-rw-r--r--test/MC/Mips/mips4/valid-xfail.s4
-rw-r--r--test/MC/Mips/mips4/valid.s4
-rw-r--r--test/MC/Mips/mips5/valid-xfail.s4
-rw-r--r--test/MC/Mips/mips5/valid.s4
-rw-r--r--test/MC/Mips/mips64/valid-xfail.s4
-rw-r--r--test/MC/Mips/mips64/valid.s4
-rw-r--r--test/MC/Mips/mips64r2/valid-xfail.s16
-rw-r--r--test/MC/Mips/mips64r2/valid.s16
-rw-r--r--test/MC/Mips/set-at-directive-explicit-at.s8
23 files changed, 929 insertions, 1069 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 2b80d3f03d..95e7d09ce0 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -23,6 +23,7 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCTargetAsmParser.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
@@ -57,7 +58,6 @@ private:
namespace {
class MipsAsmParser : public MCTargetAsmParser {
-
MipsTargetStreamer &getTargetStreamer() {
MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
return static_cast<MipsTargetStreamer &>(TS);
@@ -66,7 +66,6 @@ class MipsAsmParser : public MCTargetAsmParser {
MCSubtargetInfo &STI;
MCAsmParser &Parser;
MipsAssemblerOptions Options;
- bool hasConsumedDollar;
#define GET_ASSEMBLER_HEADER
#include "MipsGenAsmMatcher.inc"
@@ -76,8 +75,15 @@ 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);
@@ -85,95 +91,36 @@ class MipsAsmParser : public MCTargetAsmParser {
bool ParseDirective(AsmToken DirectiveID);
MipsAsmParser::OperandMatchResultTy
- parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
-
- MipsAsmParser::OperandMatchResultTy
- parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
-
- MipsAsmParser::OperandMatchResultTy
- parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- int RegKind);
-
- MipsAsmParser::OperandMatchResultTy
parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
- 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 MatchAnyRegisterNameWithoutDollar(
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
+ SMLoc S);
MipsAsmParser::OperandMatchResultTy
- parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
+ SMLoc S);
MipsAsmParser::OperandMatchResultTy
- parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy
- parseMSA128BRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy
- parseMSA128HRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseMSA128WRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseMSA128DRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
-
- MipsAsmParser::OperandMatchResultTy
- parseMSA128CtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseJumpTarget(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy
parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy
- parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
- bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- unsigned RegKind);
+ bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
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,
@@ -235,8 +182,6 @@ class MipsAsmParser : public MCTargetAsmParser {
bool eatComma(StringRef ErrorStr);
- int matchRegisterName(StringRef Symbol, bool is64BitReg);
-
int matchCPURegisterName(StringRef Symbol);
int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
@@ -251,17 +196,12 @@ class MipsAsmParser : public MCTargetAsmParser {
int matchMSA128CtrlRegisterName(StringRef Name);
- int regKindToRegClass(int RegKind);
-
unsigned getReg(int RC, int RegNo);
unsigned getGPR(int RegNo);
int getATReg();
- // Warn if RegNo is the current assembler temporary.
- void warnIfAssemblerTemporary(int RegNo);
-
bool processInstruction(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
@@ -287,8 +227,7 @@ class MipsAsmParser : public MCTargetAsmParser {
public:
MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
const MCInstrInfo &MII)
- : MCTargetAsmParser(), STI(sti), Parser(parser),
- hasConsumedDollar(false) {
+ : MCTargetAsmParser(), STI(sti), Parser(parser) {
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
@@ -301,6 +240,9 @@ public:
MCAsmParser &getParser() const { return Parser; }
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
+
+ /// Warn if RegNo is the current assembler temporary.
+ void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
};
}
@@ -309,53 +251,56 @@ namespace {
/// MipsOperand - Instances of this class represent a parsed Mips machine
/// instruction.
class MipsOperand : public MCParsedAsmOperand {
-
public:
- enum RegisterKind {
- Kind_None,
- Kind_GPR32,
- Kind_GPR64,
- Kind_HWRegs,
- Kind_FGR32Regs,
- Kind_FGRH32Regs,
- Kind_FGR64Regs,
- Kind_AFGR64Regs,
- Kind_CCRRegs,
- Kind_FCCRegs,
- Kind_ACC64DSP,
- Kind_LO32DSP,
- Kind_HI32DSP,
- Kind_COP2,
- Kind_MSA128BRegs,
- Kind_MSA128HRegs,
- Kind_MSA128WRegs,
- Kind_MSA128DRegs,
- Kind_MSA128CtrlRegs
+ /// Broad categories of register classes
+ /// The exact class is finalized by the render method.
+ enum RegKind {
+ RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
+ RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
+ /// isFP64())
+ RegKind_FCC = 4, /// FCC
+ RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
+ RegKind_MSACtrl = 16, /// MSA control registers
+ RegKind_COP2 = 32, /// COP2
+ RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
+ /// context).
+ RegKind_CCR = 128, /// CCR
+ RegKind_HWRegs = 256, /// HWRegs
+
+ /// Potentially any (e.g. $1)
+ RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
+ RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
+ RegKind_CCR | RegKind_HWRegs
};
private:
enum KindTy {
- k_CondCode,
- k_CoprocNum,
k_Immediate,
k_Memory,
- k_PostIndexRegister,
- k_Register,
- k_PtrReg,
- k_Token,
- k_LSAImm
+ k_PhysRegister,
+ k_RegisterIndex,
+ k_Token
} Kind;
- MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
+ MipsOperand(KindTy K, MipsAsmParser &Parser)
+ : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
+
+ /// For diagnostics, and checking the assembler temporary
+ MipsAsmParser &AsmParser;
struct Token {
const char *Data;
unsigned Length;
};
- struct RegOp {
- unsigned RegNum;
- RegisterKind Kind;
+ struct PhysRegOp {
+ unsigned Num; /// Register Number
+ };
+
+ struct RegIdxOp {
+ unsigned Index; /// Index into the register class
+ RegKind Kind; /// Bitfield of the kinds it could possibly be
+ const MCRegisterInfo *RegInfo;
};
struct ImmOp {
@@ -363,30 +308,161 @@ private:
};
struct MemOp {
- unsigned Base;
+ MipsOperand *Base;
const MCExpr *Off;
};
union {
struct Token Tok;
- struct RegOp Reg;
+ struct PhysRegOp PhysReg;
+ struct RegIdxOp RegIdx;
struct ImmOp Imm;
struct MemOp Mem;
};
SMLoc StartLoc, EndLoc;
+ /// Internal constructor for register kinds
+ static MipsOperand *CreateReg(unsigned Index, RegKind RegKind,
+ const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
+ MipsAsmParser &Parser) {
+ MipsOperand *Op = new MipsOperand(k_RegisterIndex, Parser);
+ Op->RegIdx.Index = Index;
+ Op->RegIdx.RegInfo = RegInfo;
+ Op->RegIdx.Kind = RegKind;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
public:
- void addRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getReg()));
+ /// Coerce the register to GPR32 and return the real register for the current
+ /// target.
+ unsigned getGPR32Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
+ AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
+ unsigned ClassID = Mips::GPR32RegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
}
- void addPtrRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getPtrReg()));
+ /// Coerce the register to GPR64 and return the real register for the current
+ /// target.
+ unsigned getGPR64Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
+ unsigned ClassID = Mips::GPR64RegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+private:
+ /// Coerce the register to AFGR64 and return the real register for the current
+ /// target.
+ unsigned getAFGR64Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
+ if (RegIdx.Index % 2 != 0)
+ AsmParser.Warning(StartLoc, "Float register should be even.");
+ return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
+ .getRegister(RegIdx.Index / 2);
+ }
+
+ /// Coerce the register to FGR64 and return the real register for the current
+ /// target.
+ unsigned getFGR64Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
+ return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
+ .getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to FGR32 and return the real register for the current
+ /// target.
+ unsigned getFGR32Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
+ return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
+ .getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to FGRH32 and return the real register for the current
+ /// target.
+ unsigned getFGRH32Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
+ return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
+ .getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to FCC and return the real register for the current
+ /// target.
+ unsigned getFCCReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
+ return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
+ .getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to MSA128 and return the real register for the current
+ /// target.
+ unsigned getMSA128Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
+ // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
+ // identical
+ unsigned ClassID = Mips::MSA128BRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to MSACtrl and return the real register for the
+ /// current target.
+ unsigned getMSACtrlReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
+ unsigned ClassID = Mips::MSACtrlRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to COP2 and return the real register for the
+ /// current target.
+ unsigned getCOP2Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
+ unsigned ClassID = Mips::COP2RegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to ACC64DSP and return the real register for the
+ /// current target.
+ unsigned getACC64DSPReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
+ unsigned ClassID = Mips::ACC64DSPRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to HI32DSP and return the real register for the
+ /// current target.
+ unsigned getHI32DSPReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
+ unsigned ClassID = Mips::HI32DSPRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to LO32DSP and return the real register for the
+ /// current target.
+ unsigned getLO32DSPReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
+ unsigned ClassID = Mips::LO32DSPRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to CCR and return the real register for the
+ /// current target.
+ unsigned getCCRReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
+ unsigned ClassID = Mips::CCRRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
+ /// Coerce the register to HWRegs and return the real register for the
+ /// current target.
+ unsigned getHWRegsReg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
+ unsigned ClassID = Mips::HWRegsRegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
}
+public:
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediate when possible. Null MCExpr = 0.
if (Expr == 0)
@@ -397,6 +473,85 @@ public:
Inst.addOperand(MCOperand::CreateExpr(Expr));
}
+ void addRegOperands(MCInst &Inst, unsigned N) const {
+ llvm_unreachable("Use a custom parser instead");
+ }
+
+ void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
+ }
+
+ void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
+ }
+
+ void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
+ }
+
+ void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
+ }
+
+ void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
+ }
+
+ void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
+ }
+
+ void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
+ }
+
+ void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
+ }
+
+ void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
+ }
+
+ void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
+ }
+
+ void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
+ }
+
+ void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
+ }
+
+ void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
+ }
+
+ void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
+ }
+
+ void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
+ }
+
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCExpr *Expr = getImm();
@@ -406,19 +561,38 @@ public:
void addMemOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::CreateReg(getMemBase()));
+ Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
const MCExpr *Expr = getMemOff();
addExpr(Inst, Expr);
}
- bool isReg() const { return Kind == k_Register; }
+ bool isReg() const {
+ // As a special case until we sort out the definition of div/divu, pretend
+ // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
+ if (isGPRAsmReg() && RegIdx.Index == 0)
+ return true;
+
+ return Kind == k_PhysRegister;
+ }
+ bool isRegIdx() const { return Kind == k_RegisterIndex; }
bool isImm() const { return Kind == k_Immediate; }
- bool isToken() const { return Kind == k_Token; }
+ bool isConstantImm() const {
+ return isImm() && dyn_cast<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 isMem() const { return Kind == k_Memory; }
- bool isPtrReg() const { return Kind == k_PtrReg; }
bool isInvNum() const { return Kind == k_Immediate; }
- bool isLSAImm() const { return Kind == k_LSAImm; }
+ bool isLSAImm() const {
+ if (!isConstantImm())
+ return false;
+ int64_t Val = getConstantImm();
+ return 1 <= Val && Val <= 4;
+ }
StringRef getToken() const {
assert(Kind == k_Token && "Invalid access!");
@@ -426,26 +600,27 @@ public:
}
unsigned getReg() const {
- assert((Kind == k_Register) && "Invalid access!");
- return Reg.RegNum;
- }
-
- unsigned getPtrReg() const {
- assert((Kind == k_PtrReg) && "Invalid access!");
- return Reg.RegNum;
- }
+ // As a special case until we sort out the definition of div/divu, pretend
+ // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
+ if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
+ RegIdx.Kind & RegKind_GPR)
+ return getGPR32Reg(); // FIXME: GPR64 too
- void setRegKind(RegisterKind RegKind) {
- assert((Kind == k_Register || Kind == k_PtrReg) && "Invalid access!");
- Reg.Kind = RegKind;
+ assert(Kind == k_PhysRegister && "Invalid access!");
+ return PhysReg.Num;
}
const MCExpr *getImm() const {
- assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!");
+ assert((Kind == k_Immediate) && "Invalid access!");
return Imm.Val;
}
- unsigned getMemBase() const {
+ int64_t getConstantImm() const {
+ const MCExpr *Val = getImm();
+ return static_cast<const MCConstantExpr *>(Val)->getValue();
+ }
+
+ MipsOperand *getMemBase() const {
assert((Kind == k_Memory) && "Invalid access!");
return Mem.Base;
}
@@ -455,8 +630,9 @@ public:
return Mem.Off;
}
- static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
- MipsOperand *Op = new MipsOperand(k_Token);
+ static MipsOperand *CreateToken(StringRef Str, SMLoc S,
+ MipsAsmParser &Parser) {
+ MipsOperand *Op = new MipsOperand(k_Token, Parser);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
@@ -464,43 +640,75 @@ public:
return Op;
}
- static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_Register);
- Op->Reg.RegNum = RegNum;
- Op->Reg.Kind = Kind_None;
- Op->StartLoc = S;
- Op->EndLoc = E;
- return Op;
+ /// Create a numeric register (e.g. $1). The exact register remains
+ /// unresolved until an instruction successfully matches
+ static MipsOperand *CreateNumericReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
+ return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
}
- static MipsOperand *CreatePtrReg(unsigned RegNum, SMLoc S, SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_PtrReg);
- Op->Reg.RegNum = RegNum;
- Op->Reg.Kind = Kind_None;
- Op->StartLoc = S;
- Op->EndLoc = E;
- return Op;
+ /// Create a register that is definitely a GPR.
+ /// This is typically only used for named registers such as $gp.
+ static MipsOperand *CreateGPRReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
}
- static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_Immediate);
- Op->Imm.Val = Val;
- Op->StartLoc = S;
- Op->EndLoc = E;
- return Op;
+ /// 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);
}
- static MipsOperand *CreateLSAImm(const MCExpr *Val, SMLoc S, SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_LSAImm);
+ /// Create a register that is definitely an FCC.
+ /// This is typically only used for named registers such as $fcc0.
+ static MipsOperand *CreateFCCReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
+ }
+
+ /// Create a register that is definitely an ACC.
+ /// This is typically only used for named registers such as $ac0.
+ static MipsOperand *CreateACCReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
+ }
+
+ /// Create a register that is definitely an MSA128.
+ /// This is typically only used for named registers such as $w0.
+ static MipsOperand *CreateMSA128Reg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
+ }
+
+ /// Create a register that is definitely an MSACtrl.
+ /// This is typically only used for named registers such as $msaaccess.
+ static MipsOperand *CreateMSACtrlReg(unsigned Index,
+ const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
+ }
+
+ static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E,
+ MipsAsmParser &Parser) {
+ MipsOperand *Op = new MipsOperand(k_Immediate, Parser);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
- static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
- SMLoc E) {
- MipsOperand *Op = new MipsOperand(k_Memory);
+ static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ MipsOperand *Op = new MipsOperand(k_Memory, Parser);
Op->Mem.Base = Base;
Op->Mem.Off = Off;
Op->StartLoc = S;
@@ -508,79 +716,33 @@ public:
return Op;
}
- bool isGPR32Asm() const {
- return Kind == k_Register && Reg.Kind == Kind_GPR32;
+ bool isGPRAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
}
- void addRegAsmOperands(MCInst &Inst, unsigned N) const {
- Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
+ bool isFGRAsmReg() const {
+ // AFGR64 is $0-$15 but we handle this in getAFGR64()
+ return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
}
-
- bool isGPR64Asm() const {
- return Kind == k_Register && Reg.Kind == Kind_GPR64;
+ bool isHWRegsAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
}
-
- bool isHWRegsAsm() const {
- assert((Kind == k_Register) && "Invalid access!");
- return Reg.Kind == Kind_HWRegs;
+ bool isCCRAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
}
-
- bool isCCRAsm() const {
- assert((Kind == k_Register) && "Invalid access!");
- return Reg.Kind == Kind_CCRRegs;
- }
-
- bool isAFGR64Asm() const {
- return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
- }
-
- bool isFGR64Asm() const {
- return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
+ bool isFCCAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7;
}
-
- bool isFGR32Asm() const {
- return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
+ bool isACCAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
}
-
- bool isFGRH32Asm() const {
- return (Kind == k_Register) && Reg.Kind == Kind_FGRH32Regs;
+ bool isCOP2AsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
}
-
- bool isFCCRegsAsm() const {
- return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs;
+ bool isMSA128AsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
}
-
- bool isACC64DSPAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_ACC64DSP;
- }
-
- bool isLO32DSPAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_LO32DSP;
- }
-
- bool isHI32DSPAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_HI32DSP;
- }
-
- bool isCOP2Asm() const { return Kind == k_Register && Reg.Kind == Kind_COP2; }
-
- bool isMSA128BAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128BRegs;
- }
-
- bool isMSA128HAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128HRegs;
- }
-
- bool isMSA128WAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128WRegs;
- }
-
- bool isMSA128DAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128DRegs;
- }
-
- bool isMSA128CRAsm() const {
- return Kind == k_Register && Reg.Kind == Kind_MSA128CtrlRegs;
+ bool isMSACtrlAsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
}
/// getStartLoc - Get the location of the first token of this operand.
@@ -589,7 +751,29 @@ public:
SMLoc getEndLoc() const { return EndLoc; }
virtual void print(raw_ostream &OS) const {
- llvm_unreachable("unimplemented!");
+ switch (Kind) {
+ case k_Immediate:
+ OS << "Imm<";
+ Imm.Val->print(OS);
+ OS << ">";
+ break;
+ case k_Memory:
+ OS << "Mem<";
+ Mem.Base->print(OS);
+ OS << ", ";
+ Mem.Off->print(OS);
+ OS << ">";
+ break;
+ case k_PhysRegister:
+ OS << "PhysReg<" << PhysReg.Num << ">";
+ break;
+ case k_RegisterIndex:
+ OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
+ break;
+ case k_Token:
+ OS << Tok.Data;
+ break;
+ }
}
}; // class MipsOperand
} // namespace
@@ -616,6 +800,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
break;
case Mips::BEQ:
case Mips::BNE:
+ case Mips::BEQ_MM:
+ case Mips::BNE_MM:
assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Offset = Inst.getOperand(2);
if (!Offset.isImm())
@@ -633,6 +819,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case Mips::BLTZAL:
case Mips::BC1F:
case Mips::BC1T:
+ case Mips::BGEZ_MM:
+ case Mips::BGTZ_MM:
+ case Mips::BLEZ_MM:
+ case Mips::BLTZ_MM:
+ case Mips::BGEZAL_MM:
+ case Mips::BLTZAL_MM:
+ case Mips::BC1F_MM:
+ case Mips::BC1T_MM:
assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Offset = Inst.getOperand(1);
if (!Offset.isImm())
@@ -996,14 +1190,13 @@ bool MipsAsmParser::MatchAndEmitInstruction(
return true;
}
-void MipsAsmParser::warnIfAssemblerTemporary(int RegNo) {
- if ((RegNo != 0) && ((int)Options.getATRegNum() == RegNo)) {
- if (RegNo == 1)
- Warning(getLexer().getLoc(), "Used $at without \".set noat\"");
+void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
+ if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
+ if (RegIndex == 1)
+ Warning(Loc, "Used $at without \".set noat\"");
else
- Warning(getLexer().getLoc(), Twine("Used $") + Twine(RegNo) +
- " with \".set at=$" + Twine(RegNo) +
- "\"");
+ Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
+ Twine(RegIndex) + "\"");
}
}
@@ -1064,8 +1257,6 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) {
.Default(-1);
}
- warnIfAssemblerTemporary(CC);
-
return CC;
}
@@ -1140,59 +1331,6 @@ int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
return CC;
}
-int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
-
- int CC;
- CC = matchCPURegisterName(Name);
- if (CC != -1)
- return matchRegisterByNumber(CC, is64BitReg ? Mips::GPR64RegClassID
- : Mips::GPR32RegClassID);
- CC = matchFPURegisterName(Name);
- // TODO: decide about fpu register class
- if (CC != -1)
- return matchRegisterByNumber(CC, isFP64() ? Mips::FGR64RegClassID
- : Mips::FGR32RegClassID);
- return matchMSA128RegisterName(Name);
-}
-
-int MipsAsmParser::regKindToRegClass(int RegKind) {
-
- switch (RegKind) {
- case MipsOperand::Kind_GPR32:
- return Mips::GPR32RegClassID;
- case MipsOperand::Kind_GPR64:
- return Mips::GPR64RegClassID;
- case MipsOperand::Kind_HWRegs:
- return Mips::HWRegsRegClassID;
- case MipsOperand::Kind_FGR32Regs:
- return Mips::FGR32RegClassID;
- case MipsOperand::Kind_FGRH32Regs:
- return Mips::FGRH32RegClassID;
- case MipsOperand::Kind_FGR64Regs:
- return Mips::FGR64RegClassID;
- case MipsOperand::Kind_AFGR64Regs:
- return Mips::AFGR64RegClassID;
- case MipsOperand::Kind_CCRRegs:
- return Mips::CCRRegClassID;
- case MipsOperand::Kind_ACC64DSP:
- return Mips::ACC64DSPRegClassID;
- case MipsOperand::Kind_FCCRegs:
- return Mips::FCCRegClassID;
- case MipsOperand::Kind_MSA128BRegs:
- return Mips::MSA128BRegClassID;
- case MipsOperand::Kind_MSA128HRegs:
- return Mips::MSA128HRegClassID;
- case MipsOperand::Kind_MSA128WRegs:
- return Mips::MSA128WRegClassID;
- case MipsOperand::Kind_MSA128DRegs:
- return Mips::MSA128DRegClassID;
- case MipsOperand::Kind_MSA128CtrlRegs:
- return Mips::MSACtrlRegClassID;
- default:
- return -1;
- }
-}
-
bool MipsAssemblerOptions::setATReg(unsigned Reg) {
if (Reg > 31)
return false;
@@ -1222,45 +1360,14 @@ int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
return -1;
- if (RegClass == Mips::GPR32RegClassID || RegClass == Mips::GPR64RegClassID)
- warnIfAssemblerTemporary(RegNum);
-
return getReg(RegClass, RegNum);
}
-int MipsAsmParser::tryParseRegister(bool is64BitReg) {
- const AsmToken &Tok = Parser.getTok();
- int RegNum = -1;
-
- if (Tok.is(AsmToken::Identifier)) {
- std::string lowerCase = Tok.getString().lower();
- RegNum = matchRegisterName(lowerCase, is64BitReg);
- } else if (Tok.is(AsmToken::Integer))
- RegNum = matchRegisterByNumber(static_cast<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);
@@ -1272,6 +1379,8 @@ 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");
@@ -1279,29 +1388,15 @@ 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;
-
- Parser.Lex(); // Eat the dollar
- if (tryParseRegisterOperand(Operands, isGP64()))
- return true;
- if (!getLexer().is(AsmToken::RParen))
- return true;
-
- S = Parser.getTok().getLoc();
- Operands.push_back(MipsOperand::CreateToken(")", S));
- Parser.Lex();
- }
+ // Almost all registers have been parsed by custom parsers. There is only
+ // one exception to this. $zero (and it's alias $0) will reach this point
+ // for div, divu, and similar instructions because it is not an operand
+ // to the instruction definition but an explicit register. Special case
+ // this situation for now.
+ if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
return false;
- }
+
// Maybe it is a symbol reference.
StringRef Identifier;
if (Parser.parseIdentifier(Identifier))
@@ -1313,47 +1408,18 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
const MCExpr *Res =
MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
- Operands.push_back(MipsOperand::CreateImm(Res, S, E));
+ Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
return false;
}
- case AsmToken::Identifier:
- // For instruction aliases like "bc1f $Label" dedicated parser will
- // eat the '$' sign before failing. So in order to look for appropriate
- // label we must check first if we have already consumed '$'.
- if (hasConsumedDollar) {
- hasConsumedDollar = false;
- SMLoc S = Parser.getTok().getLoc();
- StringRef Identifier;
- if (Parser.parseIdentifier(Identifier))
- return true;
- SMLoc E =
- SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
- // Create a symbol reference.
- const MCExpr *Res =
- MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
-
- Operands.push_back(MipsOperand::CreateImm(Res, S, E));
- return false;
- }
- // Look for the existing symbol, we should check if
- // we need to assign the proper RegisterKind.
- if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
- return false;
// Else drop to expression parsing.
case AsmToken::LParen:
case AsmToken::Minus:
case AsmToken::Plus:
case AsmToken::Integer:
case AsmToken::String: {
- // Quoted label names.
- const MCExpr *IdVal;
- SMLoc S = Parser.getTok().getLoc();
- if (getParser().parseExpression(IdVal))
- return true;
- SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
- return false;
+ DEBUG(dbgs() << ".. generic integer\n");
+ OperandMatchResultTy ResTy = ParseImm(Operands);
+ return ResTy != MatchOperand_Success;
}
case AsmToken::Percent: {
// It is a symbol reference or constant expression.
@@ -1364,7 +1430,7 @@ MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
+ Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
return false;
} // case AsmToken::Percent
} // switch(getLexer().getKind())
@@ -1496,9 +1562,27 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) {
- StartLoc = Parser.getTok().getLoc();
- RegNo = tryParseRegister(isGP64());
- EndLoc = Parser.getTok().getLoc();
+ SmallVector<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);
return (RegNo == (unsigned)-1);
}
@@ -1532,7 +1616,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;
@@ -1555,7 +1639,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
if (Mnemonic->getToken() == "la") {
SMLoc E =
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
+ Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
return MatchOperand_Success;
}
if (Tok.is(AsmToken::EndOfStatement)) {
@@ -1563,8 +1647,9 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
// Zero register assumed, add a memory operand with ZERO as its base.
- Operands.push_back(MipsOperand::CreateMem(
- isGP64() ? Mips::ZERO_64 : Mips::ZERO, IdVal, S, E));
+ MipsOperand *Base = MipsOperand::CreateGPRReg(
+ 0, getContext().getRegisterInfo(), S, E, *this);
+ Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
return MatchOperand_Success;
}
Error(Parser.getTok().getLoc(), "'(' expected");
@@ -1574,8 +1659,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Parser.Lex(); // Eat the '(' token.
}
- Res = parseRegs(Operands, isGP64() ? (int)MipsOperand::Kind_GPR64
- : (int)MipsOperand::Kind_GPR32);
+ Res = ParseAnyRegister(Operands);
if (Res != MatchOperand_Success)
return Res;
@@ -1593,7 +1677,6 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
// Replace the register operand with the memory operand.
MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
- int RegNo = op->getReg();
// Remove the register from the operands.
Operands.pop_back();
// Add the memory operand.
@@ -1606,599 +1689,220 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
getContext());
}
- Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
- delete op;
+ Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this));
return MatchOperand_Success;
}
-bool MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- int RegKind) {
- // If the first token is not '$' we have an error.
- if (Parser.getTok().isNot(AsmToken::Dollar))
- return false;
-
- SMLoc S = Parser.getTok().getLoc();
- Parser.Lex();
- AsmToken::TokenKind TkKind = getLexer().getKind();
- int Reg;
+bool MipsAsmParser::searchSymbolAlias(
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- if (TkKind == AsmToken::Integer) {
- Reg = matchRegisterByNumber(Parser.getTok().getIntVal(),
- regKindToRegClass(RegKind));
- if (Reg == -1)
- return false;
- } else if (TkKind == AsmToken::Identifier) {
- if ((Reg = matchCPURegisterName(Parser.getTok().getString().lower())) == -1)
+ 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;
- Reg = getReg(regKindToRegClass(RegKind), Reg);
- } else {
- 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;
+ }
}
-
- MipsOperand *Op = MipsOperand::CreatePtrReg(Reg, S, Parser.getTok().getLoc());
- Op->setRegKind((MipsOperand::RegisterKind)RegKind);
- Operands.push_back(Op);
- Parser.Lex();
- return true;
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- MipsOperand::RegisterKind RegKind =
- isN64() ? MipsOperand::Kind_GPR64 : MipsOperand::Kind_GPR32;
-
- // Parse index register.
- if (!parsePtrReg(Operands, RegKind))
- return MatchOperand_NoMatch;
-
- // Parse '('.
- if (Parser.getTok().isNot(AsmToken::LParen))
- return MatchOperand_NoMatch;
-
- Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
- Parser.Lex();
-
- // Parse base register.
- if (!parsePtrReg(Operands, RegKind))
- return MatchOperand_NoMatch;
-
- // Parse ')'.
- if (Parser.getTok().isNot(AsmToken::RParen))
- return MatchOperand_NoMatch;
-
- Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
- Parser.Lex();
-
- return MatchOperand_Success;
+ return false;
}
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();
- }
+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;
}
- return MatchOperand_NoMatch;
-}
-
-bool MipsAsmParser::validateMSAIndex(int Val, int RegKind) {
- MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
- if (Val < 0)
- return false;
-
- switch (Kind) {
- default:
- return false;
- case MipsOperand::Kind_MSA128BRegs:
- return Val < 16;
- case MipsOperand::Kind_MSA128HRegs:
- return Val < 8;
- case MipsOperand::Kind_MSA128WRegs:
- return Val < 4;
- case MipsOperand::Kind_MSA128DRegs:
- return Val < 2;
+ Index = matchFPURegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateFGRReg(
+ 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 = matchFCCRegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateFCCReg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
+ return MatchOperand_Success;
}
- 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))
+ Index = matchACRegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateACCReg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
+ }
- MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
-
- Operands.push_back(MipsOperand::CreateToken("[", Parser.getTok().getLoc()));
- Parser.Lex(); // Parse the '[' token.
-
- if (Parser.getTok().is(AsmToken::Dollar)) {
- // This must be a GPR.
- MipsOperand *RegOp;
- SMLoc VIdx = Parser.getTok().getLoc();
- Parser.Lex(); // Parse the '$' token.
-
- // GPR have aliases and we must account for that. Example: $30 == $fp
- if (getLexer().getKind() == AsmToken::Integer) {
- unsigned RegNum = Parser.getTok().getIntVal();
- int Reg = matchRegisterByNumber(
- RegNum, regKindToRegClass(MipsOperand::Kind_GPR32));
- if (Reg == -1) {
- Error(VIdx, "invalid general purpose register");
- return MatchOperand_ParseFail;
- }
-
- RegOp = MipsOperand::CreateReg(Reg, VIdx, Parser.getTok().getLoc());
- } else if (getLexer().getKind() == AsmToken::Identifier) {
- int RegNum = -1;
- std::string RegName = Parser.getTok().getString().lower();
-
- RegNum = matchCPURegisterName(RegName);
- if (RegNum == -1) {
- Error(VIdx, "general purpose register expected");
- return MatchOperand_ParseFail;
- }
- RegNum = getReg(regKindToRegClass(MipsOperand::Kind_GPR32), RegNum);
- RegOp = MipsOperand::CreateReg(RegNum, VIdx, Parser.getTok().getLoc());
- } else
- return MatchOperand_ParseFail;
-
- RegOp->setRegKind(MipsOperand::Kind_GPR32);
- Operands.push_back(RegOp);
- Parser.Lex(); // Eat the register identifier.
-
- if (Parser.getTok().isNot(AsmToken::RBrac))
- return MatchOperand_ParseFail;
-
- Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
- Parser.Lex(); // Parse the ']' token.
-
+ Index = matchMSA128RegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateMSA128Reg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
- // The index must be a constant expression then.
- SMLoc VIdx = Parser.getTok().getLoc();
- const MCExpr *ImmVal;
-
- if (getParser().parseExpression(ImmVal))
- return MatchOperand_ParseFail;
-
- const MCConstantExpr *expr = dyn_cast<MCConstantExpr>(ImmVal);
- if (!expr || !validateMSAIndex((int)expr->getValue(), Kind)) {
- Error(VIdx, "invalid immediate value");
- return MatchOperand_ParseFail;
+ Index = matchMSA128CtrlRegisterName(Identifier);
+ if (Index != -1) {
+ Parser.Lex();
+ Operands.push_back(MipsOperand::CreateMSACtrlReg(
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
+ return MatchOperand_Success;
}
- SMLoc E = Parser.getTok().getEndLoc();
-
- if (Parser.getTok().isNot(AsmToken::RBrac))
- return MatchOperand_ParseFail;
-
- bool insve =
- Mnemonic->getToken() == "insve.b" || Mnemonic->getToken() == "insve.h" ||
- Mnemonic->getToken() == "insve.w" || Mnemonic->getToken() == "insve.d";
-
- // The second vector index of insve instructions is always 0.
- if (insve && Operands.size() > 6) {
- if (expr->getValue() != 0) {
- Error(VIdx, "immediate value must be 0");
- return MatchOperand_ParseFail;
- }
- Operands.push_back(MipsOperand::CreateToken("0", VIdx));
- } else
- Operands.push_back(MipsOperand::CreateImm(expr, VIdx, E));
-
- Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
-
- Parser.Lex(); // Parse the ']' token.
-
- return MatchOperand_Success;
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
- int RegKind) {
- MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
-
- if (Kind != MipsOperand::Kind_MSA128CtrlRegs)
- return MatchOperand_NoMatch;
-
- if (Parser.getTok().isNot(AsmToken::Dollar))
- return MatchOperand_ParseFail;
-
- SMLoc S = Parser.getTok().getLoc();
-
- Parser.Lex(); // Eat the '$' symbol.
-
- int RegNum = -1;
- if (getLexer().getKind() == AsmToken::Identifier)
- RegNum = matchMSA128CtrlRegisterName(Parser.getTok().getString().lower());
- else if (getLexer().getKind() == AsmToken::Integer)
- RegNum = Parser.getTok().getIntVal();
- else
- return MatchOperand_ParseFail;
-
- if (RegNum < 0 || RegNum > 7)
- return MatchOperand_ParseFail;
-
- int RegVal = getReg(regKindToRegClass(Kind), RegNum);
- if (RegVal == -1)
- return MatchOperand_ParseFail;
-
- MipsOperand *RegOp =
- MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
- RegOp->setRegKind(MipsOperand::Kind_MSA128CtrlRegs);
- Operands.push_back(RegOp);
- Parser.Lex(); // Eat the register identifier.
-
- return MatchOperand_Success;
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-
- if (!isGP64())
- return MatchOperand_NoMatch;
- return parseRegs(Operands, (int)MipsOperand::Kind_GPR64);
+ return MatchOperand_NoMatch;
}
MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_GPR32);
-}
-
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAFGR64Regs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
-
- if (isFP64())
- return MatchOperand_NoMatch;
- return parseRegs(Operands, (int)MipsOperand::Kind_AFGR64Regs);
-}
+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::OperandMatchResultTy
-MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- if (!isFP64())
- return MatchOperand_NoMatch;
- return parseRegs(Operands, (int)MipsOperand::Kind_FGR64Regs);
-}
+ DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_FGR32Regs);
+ return MatchOperand_NoMatch;
}
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseFGRH32Regs(
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_FGRH32Regs);
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_FCCRegs);
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_ACC64DSP);
-}
-
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- // If the first token is not '$' we have an error.
- if (Parser.getTok().isNot(AsmToken::Dollar))
- return MatchOperand_NoMatch;
-
- SMLoc S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat the '$'
-
- const AsmToken &Tok = Parser.getTok(); // Get next token.
+ DEBUG(dbgs() << "ParseAnyRegister\n");
- if (Tok.isNot(AsmToken::Identifier))
- return MatchOperand_NoMatch;
-
- if (!Tok.getIdentifier().startswith("ac"))
- return MatchOperand_NoMatch;
+ auto Token = Parser.getTok();
- StringRef NumString = Tok.getIdentifier().substr(2);
+ SMLoc S = Token.getLoc();
- unsigned IntVal;
- if (NumString.getAsInteger(10, IntVal))
+ if (Token.isNot(AsmToken::Dollar)) {
+ DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
+ if (Token.is(AsmToken::Identifier)) {
+ if (searchSymbolAlias(Operands))
+ return MatchOperand_Success;
+ }
+ DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
return MatchOperand_NoMatch;
+ }
+ DEBUG(dbgs() << ".. $\n");
+ Parser.Lex();
+ Token = Parser.getTok();
- 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;
+ 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::parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- // If the first token is not '$' we have an error.
- if (Parser.getTok().isNot(AsmToken::Dollar))
+MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+ switch (getLexer().getKind()) {
+ default:
return MatchOperand_NoMatch;
+ case AsmToken::LParen:
+ case AsmToken::Minus:
+ case AsmToken::Plus:
+ case AsmToken::Integer:
+ case AsmToken::String:
+ break;
+ }
+ const MCExpr *IdVal;
SMLoc S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat the '$'
-
- const AsmToken &Tok = Parser.getTok(); // Get next token.
-
- if (Tok.isNot(AsmToken::Identifier))
- return MatchOperand_NoMatch;
-
- if (!Tok.getIdentifier().startswith("ac"))
- return MatchOperand_NoMatch;
-
- StringRef NumString = Tok.getIdentifier().substr(2);
-
- unsigned IntVal;
- if (NumString.getAsInteger(10, IntVal))
- return MatchOperand_NoMatch;
-
- unsigned Reg = matchRegisterByNumber(IntVal, Mips::HI32DSPRegClassID);
-
- MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
- Op->setRegKind(MipsOperand::Kind_HI32DSP);
- Operands.push_back(Op);
+ if (getParser().parseExpression(IdVal))
+ return MatchOperand_ParseFail;
- Parser.Lex(); // Eat the register number.
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
return MatchOperand_Success;
}
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- // If the first token is not '$' we have an error.
- if (Parser.getTok().isNot(AsmToken::Dollar))
- return MatchOperand_NoMatch;
-
- SMLoc S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat the '$'
-
- const AsmToken &Tok = Parser.getTok(); // Get next token.
-
- if (Tok.isNot(AsmToken::Integer))
- return MatchOperand_NoMatch;
-
- unsigned IntVal = Tok.getIntVal();
-
- unsigned Reg = matchRegisterByNumber(IntVal, Mips::COP2RegClassID);
-
- MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
- Op->setRegKind(MipsOperand::Kind_COP2);
- Operands.push_back(Op);
+MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+ DEBUG(dbgs() << "ParseJumpTarget\n");
- Parser.Lex(); // Eat the register number.
- return MatchOperand_Success;
-}
+ SMLoc S = getLexer().getLoc();
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128BRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128BRegs);
-}
+ // Integers and expressions are acceptable
+ OperandMatchResultTy ResTy = ParseImm(Operands);
+ if (ResTy != MatchOperand_NoMatch)
+ return ResTy;
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128HRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128HRegs);
-}
+ // 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;
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128WRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128WRegs);
-}
+ // 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;
+ }
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128DRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128DRegs);
-}
+ StringRef Identifier;
+ if (Parser.parseIdentifier(Identifier))
+ return hasConsumedDollar ? MatchOperand_ParseFail : MatchOperand_NoMatch;
-MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128CtrlRegs(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseMSACtrlRegs(Operands, (int)MipsOperand::Kind_MSA128CtrlRegs);
-}
+ if (hasConsumedDollar)
+ Identifier = StringRef("$" + Identifier.str());
-bool MipsAsmParser::searchSymbolAlias(
- SmallVectorImpl<MCParsedAsmOperand *> &Operands, unsigned RegKind) {
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
- 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;
-}
+ // Create a symbol reference.
+ const MCExpr *Res =
+ MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_HWRegs);
-}
+ Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
+ return MatchOperand_Success;
+ // // Look for the existing symbol, we should check if
+ // // we need to assign the proper RegisterKind.
+ // if (searchSymbolAlias(Operands))
+ // return false;
-MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
- return parseRegs(Operands, (int)MipsOperand::Kind_CCRRegs);
+ return MatchOperand_NoMatch;
}
MipsAsmParser::OperandMatchResultTy
@@ -2215,12 +1919,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));
+ MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
return MatchOperand_Success;
}
MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
+MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
switch (getLexer().getKind()) {
default:
return MatchOperand_NoMatch;
@@ -2254,7 +1958,7 @@ MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
}
Operands.push_back(
- MipsOperand::CreateLSAImm(Expr, S, Parser.getTok().getLoc()));
+ MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
return MatchOperand_Success;
}
@@ -2292,16 +1996,74 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
return VK;
}
+/// Sometimes (i.e. load/stores) the operand may be followed immediately by
+/// either this.
+/// ::= '(', register, ')'
+/// handle it before we iterate so we don't get tripped up by the lack of
+/// a comma.
+bool MipsAsmParser::ParseParenSuffix(
+ StringRef Name, SmallVectorImpl<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));
+ Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
// Read the remaining operands.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
@@ -2311,6 +2073,9 @@ bool MipsAsmParser::ParseInstruction(
Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
}
+ if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
+ return true;
+ // AFAIK, parenthesis suffixes are never on the first operand
while (getLexer().is(AsmToken::Comma)) {
Parser.Lex(); // Eat the comma.
@@ -2320,6 +2085,13 @@ bool MipsAsmParser::ParseInstruction(
Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
}
+ // Parse bracket and parenthesis suffixes before we iterate
+ if (getLexer().is(AsmToken::LBrac)) {
+ if (ParseBracketSuffix(Name, Operands))
+ return true;
+ } else if (getLexer().is(AsmToken::LParen) &&
+ ParseParenSuffix(Name, Operands))
+ return true;
}
}
if (getLexer().isNot(AsmToken::EndOfStatement)) {
diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index a543840132..fc3b922602 100644
--- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -263,6 +263,11 @@ static DecodeStatus DecodeExtSize(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+/// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't
+/// handle.
+template <typename InsnType>
+static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address,
+ const void *Decoder);
namespace llvm {
extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
TheMips64elTarget;
@@ -304,9 +309,54 @@ extern "C" void LLVMInitializeMipsDisassembler() {
createMips64elDisassembler);
}
-
#include "MipsGenDisassemblerTables.inc"
+template <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;
+}
+
/// readInstruction - read four bytes from the MemoryObject
/// and return 32 bit word sorted according to the given endianess
static DecodeStatus readInstruction32(const MemoryObject &region,
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 04520b7a22..abf36daab4 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -197,6 +197,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
case MipsISD::ILVR: return "MipsISD::ILVR";
case MipsISD::PCKEV: return "MipsISD::PCKEV";
case MipsISD::PCKOD: return "MipsISD::PCKOD";
+ case MipsISD::INSVE: return "MipsISD::INSVE";
default: return NULL;
}
}
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
index 5a105ffc89..35dd39617f 100644
--- a/lib/Target/Mips/MipsISelLowering.h
+++ b/lib/Target/Mips/MipsISelLowering.h
@@ -184,6 +184,9 @@ namespace llvm {
PCKEV, // Pack even elements
PCKOD, // Pack odd elements
+ // Vector Lane Copy
+ INSVE, // Copy element from one vector to another
+
// Combined (XOR (OR $a, $b), -1)
VNOR,
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index af4fa6410c..71d0a18d48 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -236,17 +236,27 @@ include "MipsInstrFormats.td"
// Mips Operand, Complex Patterns and Transformations Definitions.
//===----------------------------------------------------------------------===//
+def MipsJumpTargetAsmOperand : AsmOperandClass {
+ let Name = "JumpTarget";
+ let ParserMethod = "ParseJumpTarget";
+ let PredicateMethod = "isImm";
+ let RenderMethod = "addImmOperands";
+}
+
// Instruction operand types
def jmptarget : Operand<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>;
@@ -268,6 +278,11 @@ 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";
@@ -295,12 +310,6 @@ def MipsInvertedImmoperand : AsmOperandClass {
let ParserMethod = "parseInvNum";
}
-def PtrRegAsmOperand : AsmOperandClass {
- let Name = "PtrReg";
- let ParserMethod = "parsePtrReg";
-}
-
-
def InvertedImOperand : Operand<i32> {
let ParserMatchClass = MipsInvertedImmoperand;
}
@@ -332,7 +341,7 @@ def mem_ea : Operand<iPTR> {
def PtrRC : Operand<iPTR> {
let MIOperandInfo = (ops ptr_rc);
let DecoderMethod = "DecodePtrRegisterClass";
- let ParserMatchClass = PtrRegAsmOperand;
+ let ParserMatchClass = GPR32AsmOperand;
}
// size operand of ext instruction
@@ -360,6 +369,9 @@ def HI16 : 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()); }]>;
diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td
index 4a30d5ae96..5722c6cf00 100644
--- a/lib/Target/Mips/MipsMSAInstrInfo.td
+++ b/lib/Target/Mips/MipsMSAInstrInfo.td
@@ -27,6 +27,9 @@ def SDT_SHF : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>,
SDTCisVT<1, i32>, SDTCisSameAs<0, 2>]>;
def SDT_ILV : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>,
SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>]>;
+def SDT_INSVE : SDTypeProfile<1, 4, [SDTCisVec<0>, SDTCisSameAs<0, 1>,
+ SDTCisVT<2, i32>, SDTCisSameAs<0, 3>,
+ SDTCisVT<4, i32>]>;
def MipsVAllNonZero : SDNode<"MipsISD::VALL_NONZERO", SDT_MipsVecCond>;
def MipsVAnyNonZero : SDNode<"MipsISD::VANY_NONZERO", SDT_MipsVecCond>;
@@ -50,6 +53,7 @@ def MipsILVL : SDNode<"MipsISD::ILVL", SDT_ILV>;
def MipsILVR : SDNode<"MipsISD::ILVR", SDT_ILV>;
def MipsPCKEV : SDNode<"MipsISD::PCKEV", SDT_ILV>;
def MipsPCKOD : SDNode<"MipsISD::PCKOD", SDT_ILV>;
+def MipsINSVE : SDNode<"MipsISD::INSVE", SDT_INSVE>;
def vsetcc : SDNode<"ISD::SETCC", SDT_VSetCC>;
def vfsetcc : SDNode<"ISD::SETCC", SDT_VFSetCC>;
@@ -69,7 +73,7 @@ def uimm2 : Operand<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";
}
@@ -156,6 +160,15 @@ def vinsert_v4i32 : PatFrag<(ops node:$vec, node:$val, node:$idx),
def vinsert_v2i64 : PatFrag<(ops node:$vec, node:$val, node:$idx),
(v2i64 (vector_insert node:$vec, node:$val, node:$idx))>;
+def insve_v16i8 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
+ (v16i8 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
+def insve_v8i16 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
+ (v8i16 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
+def insve_v4i32 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
+ (v4i32 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
+def insve_v2i64 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2),
+ (v2i64 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>;
+
class vfsetcc_type<ValueType ResTy, ValueType OpTy, CondCode CC> :
PatFrag<(ops node:$lhs, node:$rhs),
(ResTy (vfsetcc (OpTy node:$lhs), (OpTy node:$rhs), CC))>;
@@ -1402,9 +1415,9 @@ class MSA_3R_SPLAT_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
RegisterOperand ROWD, RegisterOperand ROWS = ROWD,
InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs ROWD:$wd);
- dag InOperandList = (ins ROWS:$ws, GPR32:$rt);
+ dag InOperandList = (ins ROWS:$ws, GPR32Opnd:$rt);
string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$rt]");
- list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, GPR32:$rt))];
+ list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, GPR32Opnd:$rt))];
InstrItinClass Itinerary = itin;
}
@@ -1425,10 +1438,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, GPR32:$rt);
+ dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, GPR32Opnd:$rt);
string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$rt]");
list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROWS:$ws,
- GPR32:$rt))];
+ GPR32Opnd:$rt))];
InstrItinClass Itinerary = itin;
string Constraints = "$wd = $wd_in";
}
@@ -1496,11 +1509,12 @@ class MSA_INSVE_DESC_BASE<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);
- string AsmString = !strconcat(instr_asm, "\t$wd[$n], $ws[0]");
+ dag InOperandList = (ins ROWD:$wd_in, uimm6:$n, ROWS:$ws, uimmz:$n2);
+ string AsmString = !strconcat(instr_asm, "\t$wd[$n], $ws[$n2]");
list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in,
immZExt6:$n,
- ROWS:$ws))];
+ ROWS:$ws,
+ immz:$n2))];
InstrItinClass Itinerary = itin;
string Constraints = "$wd = $wd_in";
}
@@ -2291,13 +2305,13 @@ class INSERT_FW_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<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", int_mips_insve_b,
+class INSVE_B_DESC : MSA_INSVE_DESC_BASE<"insve.b", insve_v16i8,
MSA128BOpnd>;
-class INSVE_H_DESC : MSA_INSVE_DESC_BASE<"insve.h", int_mips_insve_h,
+class INSVE_H_DESC : MSA_INSVE_DESC_BASE<"insve.h", insve_v8i16,
MSA128HOpnd>;
-class INSVE_W_DESC : MSA_INSVE_DESC_BASE<"insve.w", int_mips_insve_w,
+class INSVE_W_DESC : MSA_INSVE_DESC_BASE<"insve.w", insve_v4i32,
MSA128WOpnd>;
-class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", int_mips_insve_d,
+class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", insve_v2i64,
MSA128DOpnd>;
class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
@@ -3188,10 +3202,14 @@ def INSERT_D : INSERT_D_ENC, INSERT_D_DESC;
// INSERT_FW_PSEUDO defined after INSVE_W
// INSERT_FD_PSEUDO defined after INSVE_D
-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;
+// 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 INSERT_FW_PSEUDO : INSERT_FW_PSEUDO_DESC;
def INSERT_FD_PSEUDO : INSERT_FD_PSEUDO_DESC;
diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td
index f5e0bf5f00..834e6c5fc7 100644
--- a/lib/Target/Mips/MipsRegisterInfo.td
+++ b/lib/Target/Mips/MipsRegisterInfo.td
@@ -209,7 +209,8 @@ let Namespace = "Mips" in {
def PC : Register<"pc">;
// Hardware register $29
- def HWR29 : MipsReg<29, "29">;
+ foreach I = 0-31 in
+ def HWR#I : MipsReg<#I, ""#I>;
// Accum registers
foreach I = 0-3 in
@@ -364,7 +365,8 @@ def LO64 : RegisterClass<"Mips", [i64], 64, (add LO0_64)>;
def HI64 : RegisterClass<"Mips", [i64], 64, (add HI0_64)>;
// Hardware registers
-def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>, Unallocatable;
+def HWRegs : RegisterClass<"Mips", [i32], 32, (sequence "HWR%u", 0, 31)>,
+ Unallocatable;
// Accumulator Registers
def ACC64 : RegisterClass<"Mips", [untyped], 64, (add AC0)> {
@@ -394,86 +396,68 @@ def OCTEON_P : RegisterClass<"Mips", [i64], 64, (add P0, P1, P2)>,
// Register Operands.
class MipsAsmRegOperand : AsmOperandClass {
- let RenderMethod = "addRegAsmOperands";
-}
-def GPR32AsmOperand : MipsAsmRegOperand {
- let Name = "GPR32Asm";
- let ParserMethod = "parseGPR32";
+ let ParserMethod = "ParseAnyRegister";
}
def GPR64AsmOperand : MipsAsmRegOperand {
- let Name = "GPR64Asm";
- let ParserMethod = "parseGPR64";
+ let Name = "GPR64AsmReg";
+ let PredicateMethod = "isGPRAsmReg";
}
-def ACC64DSPAsmOperand : MipsAsmRegOperand {
- let Name = "ACC64DSPAsm";
- let ParserMethod = "parseACC64DSP";
+def GPR32AsmOperand : MipsAsmRegOperand {
+ let Name = "GPR32AsmReg";
+ let PredicateMethod = "isGPRAsmReg";
}
-def LO32DSPAsmOperand : MipsAsmRegOperand {
- let Name = "LO32DSPAsm";
- let ParserMethod = "parseLO32DSP";
+def ACC64DSPAsmOperand : MipsAsmRegOperand {
+ let Name = "ACC64DSPAsmReg";
+ let PredicateMethod = "isACCAsmReg";
}
def HI32DSPAsmOperand : MipsAsmRegOperand {
- let Name = "HI32DSPAsm";
- let ParserMethod = "parseHI32DSP";
+ let Name = "HI32DSPAsmReg";
+ let PredicateMethod = "isACCAsmReg";
+}
+
+def LO32DSPAsmOperand : MipsAsmRegOperand {
+ let Name = "LO32DSPAsmReg";
+ let PredicateMethod = "isACCAsmReg";
}
def CCRAsmOperand : MipsAsmRegOperand {
- let Name = "CCRAsm";
- let ParserMethod = "parseCCRRegs";
+ let Name = "CCRAsmReg";
}
def AFGR64AsmOperand : MipsAsmRegOperand {
- let Name = "AFGR64Asm";
- let ParserMethod = "parseAFGR64Regs";
+ let Name = "AFGR64AsmReg";
+ let PredicateMethod = "isFGRAsmReg";
}
def FGR64AsmOperand : MipsAsmRegOperand {
- let Name = "FGR64Asm";
- let ParserMethod = "parseFGR64Regs";
+ let Name = "FGR64AsmReg";
+ let PredicateMethod = "isFGRAsmReg";
}
def FGR32AsmOperand : MipsAsmRegOperand {
- let Name = "FGR32Asm";
- let ParserMethod = "parseFGR32Regs";
+ let Name = "FGR32AsmReg";
+ let PredicateMethod = "isFGRAsmReg";
}
def FGRH32AsmOperand : MipsAsmRegOperand {
- let Name = "FGRH32Asm";
- let ParserMethod = "parseFGRH32Regs";
+ let Name = "FGRH32AsmReg";
+ let PredicateMethod = "isFGRAsmReg";
}
def FCCRegsAsmOperand : MipsAsmRegOperand {
- let Name = "FCCRegsAsm";
- let ParserMethod = "parseFCCRegs";
-}
-
-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";
+ let Name = "FCCAsmReg";
}
-def MSA128DAsmOperand : MipsAsmRegOperand {
- let Name = "MSA128DAsm";
- let ParserMethod = "parseMSA128DRegs";
+def MSA128AsmOperand : MipsAsmRegOperand {
+ let Name = "MSA128AsmReg";
}
-def MSA128CRAsmOperand : MipsAsmRegOperand {
- let Name = "MSA128CRAsm";
- let ParserMethod = "parseMSA128CtrlRegs";
+def MSACtrlAsmOperand : MipsAsmRegOperand {
+ let Name = "MSACtrlAsmReg";
}
def GPR32Opnd : RegisterOperand<GPR32> {
@@ -493,13 +477,11 @@ def CCROpnd : RegisterOperand<CCR> {
}
def HWRegsAsmOperand : MipsAsmRegOperand {
- let Name = "HWRegsAsm";
- let ParserMethod = "parseHWRegs";
+ let Name = "HWRegsAsmReg";
}
def COP2AsmOperand : MipsAsmRegOperand {
- let Name = "COP2Asm";
- let ParserMethod = "parseCOP2";
+ let Name = "COP2AsmReg";
}
def HWRegsOpnd : RegisterOperand<HWRegs> {
@@ -543,22 +525,22 @@ def COP2Opnd : RegisterOperand<COP2> {
}
def MSA128BOpnd : RegisterOperand<MSA128B> {
- let ParserMatchClass = MSA128BAsmOperand;
+ let ParserMatchClass = MSA128AsmOperand;
}
def MSA128HOpnd : RegisterOperand<MSA128H> {
- let ParserMatchClass = MSA128HAsmOperand;
+ let ParserMatchClass = MSA128AsmOperand;
}
def MSA128WOpnd : RegisterOperand<MSA128W> {
- let ParserMatchClass = MSA128WAsmOperand;
+ let ParserMatchClass = MSA128AsmOperand;
}
def MSA128DOpnd : RegisterOperand<MSA128D> {
- let ParserMatchClass = MSA128DAsmOperand;
+ let ParserMatchClass = MSA128AsmOperand;
}
def MSA128CROpnd : RegisterOperand<MSACtrl> {
- let ParserMatchClass = MSA128CRAsmOperand;
+ let ParserMatchClass = MSACtrlAsmOperand;
}
diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp
index 218cd15baa..0dac0b7990 100644
--- a/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -1810,6 +1810,13 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
case Intrinsic::mips_insert_d:
return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(Op), Op->getValueType(0),
Op->getOperand(1), Op->getOperand(3), Op->getOperand(2));
+ case Intrinsic::mips_insve_b:
+ case Intrinsic::mips_insve_h:
+ case Intrinsic::mips_insve_w:
+ case Intrinsic::mips_insve_d:
+ return DAG.getNode(MipsISD::INSVE, DL, Op->getValueType(0),
+ Op->getOperand(1), Op->getOperand(2), Op->getOperand(3),
+ DAG.getConstant(0, MVT::i32));
case Intrinsic::mips_ldi_b:
case Intrinsic::mips_ldi_h:
case Intrinsic::mips_ldi_w:
@@ -2837,7 +2844,8 @@ MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI,
BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_W), Wd)
.addReg(Wd_in)
.addImm(Lane)
- .addReg(Wt);
+ .addReg(Wt)
+ .addImm(0);
MI->eraseFromParent(); // The pseudo instruction is gone now.
return BB;
@@ -2870,7 +2878,8 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI,
BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_D), Wd)
.addReg(Wd_in)
.addImm(Lane)
- .addReg(Wt);
+ .addReg(Wt)
+ .addImm(0);
MI->eraseFromParent(); // The pseudo instruction is gone now.
return BB;
diff --git a/test/MC/Mips/cfi.s b/test/MC/Mips/cfi.s
new file mode 100644
index 0000000000..a3247b5479
--- /dev/null
+++ b/test/MC/Mips/cfi.s
@@ -0,0 +1,13 @@
+# RUN: llvm-mc %s -triple=mips-unknown-unknown -show-encoding -mcpu=mips32 | \
+# RUN: FileCheck %s
+# RUN: llvm-mc %s -triple=mips64-unknown-unknown -show-encoding -mcpu=mips64 | \
+# RUN: FileCheck %s
+
+# Check that we can accept register names in CFI directives and that they are
+# canonicalised to their DWARF register numbers.
+
+ .cfi_startproc # CHECK: .cfi_startproc
+ .cfi_register $6, $5 # CHECK: .cfi_register 6, 5
+ .cfi_def_cfa $fp, 8 # CHECK: .cfi_def_cfa 30, 8
+ .cfi_def_cfa $2, 16 # CHECK: .cfi_def_cfa 2, 16
+ .cfi_endproc # CHECK: .cfi_endproc
diff --git a/test/MC/Mips/mips-register-names-invalid.s b/test/MC/Mips/mips-register-names-invalid.s
index df1054fed4..e6f8416a41 100644
--- a/test/MC/Mips/mips-register-names-invalid.s
+++ b/test/MC/Mips/mips-register-names-invalid.s
@@ -4,5 +4,5 @@
# $32 used to trigger an assertion instead of the usual error message due to
# an off-by-one bug.
-# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
add $32, $0, $0
diff --git a/test/MC/Mips/mips3/valid-xfail.s b/test/MC/Mips/mips3/valid-xfail.s
index dd4e482f38..7f802ef765 100644
--- a/test/MC/Mips/mips3/valid-xfail.s
+++ b/test/MC/Mips/mips3/valid-xfail.s
@@ -8,10 +8,6 @@
# XFAIL: *
.set noat
- ddiv $zero,$k0,$s3
- ddivu $zero,$s0,$s1
- div $zero,$t9,$t3
- divu $zero,$t9,$t7
ehb
lwc3 $10,-32265($k0)
ssnop
diff --git a/test/MC/Mips/mips3/valid.s b/test/MC/Mips/mips3/valid.s
index f5c98f0007..703d49a4ea 100644
--- a/test/MC/Mips/mips3/valid.s
+++ b/test/MC/Mips/mips3/valid.s
@@ -35,8 +35,12 @@
dadd $s3,$at,$ra
daddi $sp,$s4,-27705
daddiu $k0,$s6,-4586
+ ddiv $zero,$k0,$s3
+ ddivu $zero,$s0,$s1
+ div $zero,$t9,$t3
div.d $f29,$f20,$f27
div.s $f4,$f5,$f15
+ divu $zero,$t9,$t7
dmfc1 $t4,$f13
dmtc1 $s0,$f14
dmult $s7,$t1
diff --git a/test/MC/Mips/mips32r2/valid-xfail.s b/test/MC/Mips/mips32r2/valid-xfail.s
index dff3ae43f1..5dbb1d3b49 100644
--- a/test/MC/Mips/mips32r2/valid-xfail.s
+++ b/test/MC/Mips/mips32r2/valid-xfail.s
@@ -2,7 +2,7 @@
# they aren't implemented yet).
# This test is set up to XPASS if any instruction generates an encoding.
#
-# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r2 | FileCheck %s
+# RUN: not llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r2 | not FileCheck %s
# CHECK-NOT: encoding
# XFAIL: *
@@ -48,7 +48,6 @@
c.nge.d $fcc5,$f21,$f16
c.nge.ps $f1,$f26
c.nge.s $fcc3,$f11,$f8
- c.ngl.d $f29,$f29
c.ngl.ps $f21,$f30
c.ngl.s $fcc2,$f31,$f23
c.ngle.ps $fcc7,$f12,$f20
@@ -66,7 +65,6 @@
c.seq.ps $fcc6,$f31,$f14
c.seq.s $fcc7,$f1,$f25
c.sf.ps $fcc6,$f4,$f6
- c.sf.s $f14,$f22
c.ueq.d $fcc4,$f13,$f25
c.ueq.ps $fcc1,$f5,$f29
c.ueq.s $fcc6,$f3,$f30
@@ -96,14 +94,10 @@
cmpu.lt.qb $at,$a3
ctcmsa $31,$s7
cvt.d.l $f4,$f16
- cvt.l.d $f24,$f15
- cvt.l.s $f11,$f29
cvt.ps.s $f3,$f18,$f19
cvt.s.l $f15,$f30
cvt.s.pl $f30,$f1
cvt.s.pu $f14,$f25
- div $zero,$t9,$t3
- divu $zero,$t9,$t7
dmt $k0
dpa.w.ph $ac1,$s7,$k0
dpaq_s.w.ph $ac2,$a0,$t5
@@ -152,8 +146,6 @@
flog2.w $w19,$w23
floor.l.d $f26,$f7
floor.l.s $f12,$f5
- floor.w.d $f14,$f11
- floor.w.s $f8,$f9
fork $s2,$t0,$a0
frcp.d $w12,$w4
frcp.w $w30,$w8
@@ -228,12 +220,8 @@
nlzc.d $w14,$w14
nlzc.h $w24,$w24
nlzc.w $w10,$w4
- nmadd.d $f18,$f9,$f14,$f19
nmadd.ps $f27,$f4,$f9,$f25
- nmadd.s $f0,$f5,$f25,$f12
- nmsub.d $f30,$f8,$f16,$f30
nmsub.ps $f6,$f12,$f14,$f17
- nmsub.s $f1,$f24,$f19,$f4
nor.v $w20,$w20,$w15
or.v $w13,$w23,$w12
packrl.ph $ra,$t8,$t6
@@ -264,7 +252,6 @@
pul.ps $f9,$f30,$f26
puu.ps $f24,$f9,$f2
raddu.w.qb $t9,$s3
- rdhwr $sp,$11
rdpgpr $s3,$t1
recip.d $f19,$f6
recip.s $f3,$f30
@@ -311,7 +298,6 @@
swe $t8,94($k0)
swle $v1,-209($gp)
swre $k0,-202($s2)
- swxc1 $f19,$t4($k0)
synci 20023($s0)
tlbginv
tlbginvf
diff --git a/test/MC/Mips/mips32r2/valid.s b/test/MC/Mips/mips32r2/valid.s
index 03f5155425..29c0807fff 100644
--- a/test/MC/Mips/mips32r2/valid.s
+++ b/test/MC/Mips/mips32r2/valid.s
@@ -11,8 +11,10 @@
addi $t5,$t1,26322
addu $t1,$a0,$a2
and $s7,$v0,$t4
+ c.ngl.d $f29,$f29
c.ngle.d $f0,$f16
c.sf.d $f30,$f0
+ c.sf.s $f14,$f22
ceil.w.d $f11,$f25
ceil.w.s $f6,$f20
cfc1 $s1,$21
@@ -21,16 +23,22 @@
ctc1 $a2,$26
cvt.d.s $f22,$f28
cvt.d.w $f26,$f11
+ cvt.l.d $f24,$f15
+ cvt.l.s $f11,$f29
cvt.s.d $f26,$f8
cvt.s.w $f22,$f15
cvt.w.d $f20,$f14
cvt.w.s $f20,$f24
deret
di $s8
+ div $zero,$t9,$t3
div.d $f29,$f20,$f27
div.s $f4,$f5,$f15
+ divu $zero,$t9,$t7
ei $t6
eret
+ floor.w.d $f14,$f11
+ floor.w.s $f8,$f9
lb $t8,-14515($t2)
lbu $t0,30195($v1)
ldc1 $f11,16391($s0)
@@ -94,9 +102,14 @@
multu $t1,$s2
neg.d $f27,$f18
neg.s $f1,$f15
+ nmadd.d $f18,$f9,$f14,$f19
+ nmadd.s $f0,$f5,$f25,$f12
+ nmsub.d $f30,$f8,$f16,$f30
+ nmsub.s $f1,$f24,$f19,$f4
nop
nor $a3,$zero,$a3
or $t4,$s0,$sp
+ rdhwr $sp,$11
round.w.d $f6,$f4
round.w.s $f27,$f28
sb $s6,-19857($t6)
@@ -126,6 +139,7 @@
swc2 $25,24880($s0)
swl $t7,13694($s3)
swr $s1,-26590($t6)
+ swxc1 $f19,$t4($k0)
teqi $s5,-17504
tgei $s1,5025
tgeiu $sp,-28621
diff --git a/test/MC/Mips/mips4/valid-xfail.s b/test/MC/Mips/mips4/valid-xfail.s
index 7599164af0..26749a9153 100644
--- a/test/MC/Mips/mips4/valid-xfail.s
+++ b/test/MC/Mips/mips4/valid-xfail.s
@@ -36,10 +36,6 @@
c.ult.s $fcc7,$f24,$f10
c.un.d $fcc6,$f23,$f24
c.un.s $fcc1,$f30,$f4
- ddiv $zero,$k0,$s3
- ddivu $zero,$s0,$s1
- div $zero,$t9,$t3
- divu $zero,$t9,$t7
ehb
madd.d $f18,$f19,$f26,$f20
madd.s $f1,$f31,$f19,$f25
diff --git a/test/MC/Mips/mips4/valid.s b/test/MC/Mips/mips4/valid.s
index 66886c5794..bcc9f689bf 100644
--- a/test/MC/Mips/mips4/valid.s
+++ b/test/MC/Mips/mips4/valid.s
@@ -35,8 +35,12 @@
dadd $s3,$at,$ra
daddi $sp,$s4,-27705
daddiu $k0,$s6,-4586
+ ddiv $zero,$k0,$s3
+ ddivu $zero,$s0,$s1
+ div $zero,$t9,$t3
div.d $f29,$f20,$f27
div.s $f4,$f5,$f15
+ divu $zero,$t9,$t7
dmfc1 $t4,$f13
dmtc1 $s0,$f14
dmult $s7,$t1
diff --git a/test/MC/Mips/mips5/valid-xfail.s b/test/MC/Mips/mips5/valid-xfail.s
index 10931587e4..285aabbfe6 100644
--- a/test/MC/Mips/mips5/valid-xfail.s
+++ b/test/MC/Mips/mips5/valid-xfail.s
@@ -58,10 +58,6 @@
cvt.ps.s $f3,$f18,$f19
cvt.s.pl $f30,$f1
cvt.s.pu $f14,$f25
- ddiv $zero,$k0,$s3
- ddivu $zero,$s0,$s1
- div $zero,$t9,$t3
- divu $zero,$t9,$t7
ehb
madd.d $f18,$f19,$f26,$f20
madd.ps $f22,$f3,$f14,$f3
diff --git a/test/MC/Mips/mips5/valid.s b/test/MC/Mips/mips5/valid.s
index 7665d1f025..64c2ff5e78 100644
--- a/test/MC/Mips/mips5/valid.s
+++ b/test/MC/Mips/mips5/valid.s
@@ -35,8 +35,12 @@
dadd $s3,$at,$ra
daddi $sp,$s4,-27705
daddiu $k0,$s6,-4586
+ ddiv $zero,$k0,$s3
+ ddivu $zero,$s0,$s1
+ div $zero,$t9,$t3
div.d $f29,$f20,$f27
div.s $f4,$f5,$f15
+ divu $zero,$t9,$t7
dmfc1 $t4,$f13
dmtc1 $s0,$f14
dmult $s7,$t1
diff --git a/test/MC/Mips/mips64/valid-xfail.s b/test/MC/Mips/mips64/valid-xfail.s
index 11ed7747b2..66f15e03c2 100644
--- a/test/MC/Mips/mips64/valid-xfail.s
+++ b/test/MC/Mips/mips64/valid-xfail.s
@@ -60,10 +60,6 @@
cvt.ps.s $f3,$f18,$f19
cvt.s.pl $f30,$f1
cvt.s.pu $f14,$f25
- ddiv $zero,$k0,$s3
- ddivu $zero,$s0,$s1
- div $zero,$t9,$t3
- divu $zero,$t9,$t7
dmfc0 $t2,c0_watchhi,2
dmtc0 $t7,c0_datalo
ehb
diff --git a/test/MC/Mips/mips64/valid.s b/test/MC/Mips/mips64/valid.s
index cfd708ce66..673754535b 100644
--- a/test/MC/Mips/mips64/valid.s
+++ b/test/MC/Mips/mips64/valid.s
@@ -39,8 +39,12 @@
dclo $s2,$a2
dclz $s0,$t9
deret
+ ddiv $zero,$k0,$s3
+ ddivu $zero,$s0,$s1
+ div $zero,$t9,$t3
div.d $f29,$f20,$f27
div.s $f4,$f5,$f15
+ divu $zero,$t9,$t7
dmfc1 $t4,$f13
dmtc1 $s0,$f14
dmult $s7,$t1
diff --git a/test/MC/Mips/mips64r2/valid-xfail.s b/test/MC/Mips/mips64r2/valid-xfail.s
index 7279707ea0..d8aefd2a5c 100644
--- a/test/MC/Mips/mips64r2/valid-xfail.s
+++ b/test/MC/Mips/mips64r2/valid-xfail.s
@@ -52,7 +52,6 @@
c.nge.d $fcc5,$f21,$f16
c.nge.ps $f1,$f26
c.nge.s $fcc3,$f11,$f8
- c.ngl.d $f29,$f29
c.ngl.ps $f21,$f30
c.ngl.s $fcc2,$f31,$f23
c.ngle.ps $fcc7,$f12,$f20
@@ -70,7 +69,6 @@
c.seq.ps $fcc6,$f31,$f14
c.seq.s $fcc7,$f1,$f25
c.sf.ps $fcc6,$f4,$f6
- c.sf.s $f14,$f22
c.ueq.d $fcc4,$f13,$f25
c.ueq.ps $fcc1,$f5,$f29
c.ueq.s $fcc6,$f3,$f30
@@ -98,10 +96,6 @@
cmpu.lt.qb $at,$a3
cvt.s.pl $f30,$f1
cvt.s.pu $f14,$f25
- ddiv $zero,$k0,$s3
- ddivu $zero,$s0,$s1
- div $zero,$t9,$t3
- divu $zero,$t9,$t7
dmfc0 $t2,c0_watchhi,2
dmfgc0 $gp,c0_perfcnt,6
dmt $k0
@@ -124,8 +118,6 @@
dpsu.h.qbr $ac2,$a1,$s6
dpsx.w.ph $ac0,$s7,$gp
drorv $at,$a1,$s7
- dsbh $v1,$t6
- dshd $v0,$sp
dvpe $s6
ehb
emt $t0
@@ -188,7 +180,6 @@
lwx $t4,$t4($s4)
madd.d $f18,$f19,$f26,$f20
madd.ps $f22,$f3,$f14,$f3
- madd.s $f1,$f31,$f19,$f25
maq_s.w.phl $ac2,$t9,$t3
maq_s.w.phr $ac0,$t2,$t9
maq_sa.w.phl $ac3,$a1,$v1
@@ -206,7 +197,6 @@
msub $ac2,$sp,$t6
msub.d $f10,$f1,$f31,$f18
msub.ps $f12,$f14,$f29,$f17
- msub.s $f12,$f19,$f10,$f16
msubu $ac2,$a1,$t8
mtc0 $t1,c0_datahi1
mtgc0 $s4,$21,7
@@ -236,10 +226,8 @@
nlzc.w $w10,$w4
nmadd.d $f18,$f9,$f14,$f19
nmadd.ps $f27,$f4,$f9,$f25
- nmadd.s $f0,$f5,$f25,$f12
nmsub.d $f30,$f8,$f16,$f30
nmsub.ps $f6,$f12,$f14,$f17
- nmsub.s $f1,$f24,$f19,$f4
nor.v $w20,$w20,$w15
or.v $w13,$w23,$w12
packrl.ph $ra,$t8,$t6
@@ -270,7 +258,6 @@
pul.ps $f9,$f30,$f26
puu.ps $f24,$f9,$f2
raddu.w.qb $t9,$s3
- rdhwr $sp,$11
rdpgpr $s3,$t1
recip.d $f19,$f6
recip.s $f3,$f30
@@ -282,8 +269,6 @@
rsqrt.s $f4,$f8
sbe $s7,33($s1)
sce $sp,189($t2)
- seb $t9,$t7
- seh $v1,$t4
she $t8,105($v0)
shilo $ac1,26
shilov $ac2,$t2
@@ -330,6 +315,5 @@
tlbwi
tlbwr
wrpgpr $zero,$t5
- wsbh $k1,$t1
xor.v $w20,$w21,$w30
yield $v1,$s0
diff --git a/test/MC/Mips/mips64r2/valid.s b/test/MC/Mips/mips64r2/valid.s
index e1d80199c3..4e549af9e7 100644
--- a/test/MC/Mips/mips64r2/valid.s
+++ b/test/MC/Mips/mips64r2/valid.s
@@ -11,8 +11,10 @@
addi $t5,$t1,26322
addu $t1,$a0,$a2
and $s7,$v0,$t4
+ c.ngl.d $f29,$f29
c.ngle.d $f0,$f16
c.sf.d $f30,$f0
+ c.sf.s $f14,$f22
ceil.l.d $f1,$f3
ceil.l.s $f18,$f13
ceil.w.d $f11,$f25
@@ -38,12 +40,18 @@
dclz $s0,$t9
deret
di $s8
+ ddiv $zero,$k0,$s3
+ ddivu $zero,$s0,$s1
+ div $zero,$t9,$t3
div.d $f29,$f20,$f27
div.s $f4,$f5,$f15
+ divu $zero,$t9,$t7
dmfc1 $t4,$f13
dmtc1 $s0,$f14
dmult $s7,$t1
dmultu $a1,$a2
+ dsbh $v1,$t6
+ dshd $v0,$sp
dsllv $zero,$s4,$t4
dsrav $gp,$s2,$s3
dsrlv $s3,$t6,$s4
@@ -79,6 +87,7 @@
lwxc1 $f12,$s1($s8)
madd $s6,$t5
madd $zero,$t1
+ madd.s $f1,$f31,$f19,$f25
maddu $s3,$gp
maddu $t8,$s2
mfc0 $a2,$14,1
@@ -106,6 +115,7 @@
movz.d $f12,$f29,$t1
movz.s $f25,$f7,$v1
msub $s7,$k1
+ msub.s $f12,$f19,$f10,$f16
msubu $t7,$a1
mtc1 $s8,$f9
mthc1 $zero,$f16
@@ -121,9 +131,12 @@
multu $t1,$s2
neg.d $f27,$f18
neg.s $f1,$f15
+ nmadd.s $f0,$f5,$f25,$f12
+ nmsub.s $f1,$f24,$f19,$f4
nop
nor $a3,$zero,$a3
or $t4,$s0,$sp
+ rdhwr $sp,$11
round.l.d $f12,$f1
round.l.s $f25,$f5
round.w.d $f6,$f4
@@ -137,6 +150,8 @@
sdl $a3,-20961($s8)
sdr $t3,-20423($t4)
sdxc1 $f11,$t2($t6)
+ seb $t9,$t7
+ seh $v1,$t4
sh $t6,-6704($t7)
sllv $a3,$zero,$t1
slt $s7,$t3,$k1
@@ -169,3 +184,4 @@
trunc.w.d $f22,$f15
trunc.w.s $f28,$f30
xor $s2,$a0,$s8
+ wsbh $k1,$t1
diff --git a/test/MC/Mips/set-at-directive-explicit-at.s b/test/MC/Mips/set-at-directive-explicit-at.s
index 71f1a98fae..1bd26ffa85 100644
--- a/test/MC/Mips/set-at-directive-explicit-at.s
+++ b/test/MC/Mips/set-at-directive-explicit-at.s
@@ -7,12 +7,12 @@
.text
foo:
# CHECK: jr $1 # encoding: [0x08,0x00,0x20,0x00]
-# WARNINGS: :[[@LINE+2]]:12: warning: Used $at without ".set noat"
+# WARNINGS: :[[@LINE+2]]:11: warning: Used $at without ".set noat"
.set at=$1
jr $at
# CHECK: jr $1 # encoding: [0x08,0x00,0x20,0x00]
-# WARNINGS: :[[@LINE+2]]:12: warning: Used $at without ".set noat"
+# WARNINGS: :[[@LINE+2]]:11: warning: Used $at without ".set noat"
.set at=$1
jr $1
# WARNINGS-NOT: warning: Used $at without ".set noat"
@@ -31,12 +31,12 @@ foo:
jr $at
# CHECK: jr $16 # encoding: [0x08,0x00,0x00,0x02]
-# WARNINGS: :[[@LINE+2]]:12: warning: Used $16 with ".set at=$16"
+# WARNINGS: :[[@LINE+2]]:11: warning: Used $16 with ".set at=$16"
.set at=$16
jr $s0
# CHECK: jr $16 # encoding: [0x08,0x00,0x00,0x02]
-# WARNINGS: :[[@LINE+2]]:12: warning: Used $16 with ".set at=$16"
+# WARNINGS: :[[@LINE+2]]:11: warning: Used $16 with ".set at=$16"
.set at=$16
jr $16
# WARNINGS-NOT: warning