summaryrefslogtreecommitdiff
path: root/gnu/llvm/lib
diff options
context:
space:
mode:
authorPascal Stumpf <pascal@cvs.openbsd.org>2016-09-03 22:47:02 +0000
committerPascal Stumpf <pascal@cvs.openbsd.org>2016-09-03 22:47:02 +0000
commit6e362578e8020fa6de5da1e0d11e30e360318a5a (patch)
tree86dd63849af9145bf5727ea9c67ca5a97f9498ce /gnu/llvm/lib
parent9f18fb39bd48df66a878b9f7092f8707cce051aa (diff)
Use the space freed up by sparc and zaurus to import LLVM.
ok hackroom@
Diffstat (limited to 'gnu/llvm/lib')
-rw-r--r--gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp4865
-rw-r--r--gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp528
-rw-r--r--gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td1078
-rw-r--r--gnu/llvm/lib/Target/Mips/MipsInstrInfo.td2407
-rw-r--r--gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h112
5 files changed, 2501 insertions, 6489 deletions
diff --git a/gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index f10d100bfe1..d4e061f00d3 100644
--- a/gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/gnu/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -7,71 +7,45 @@
//
//===----------------------------------------------------------------------===//
-#include "MCTargetDesc/MipsABIFlagsSection.h"
#include "MCTargetDesc/MipsABIInfo.h"
-#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsMCExpr.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
+#include "MipsRegisterInfo.h"
+#include "MipsTargetObjectFile.h"
#include "MipsTargetStreamer.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCAsmParserExtension.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
#include <memory>
-#include <string>
-#include <utility>
using namespace llvm;
#define DEBUG_TYPE "mips-asm-parser"
namespace llvm {
-
class MCInstrInfo;
-
-} // end namespace llvm
-
-extern cl::opt<bool> EmitJalrReloc;
+}
namespace {
-
class MipsAssemblerOptions {
public:
- MipsAssemblerOptions(const FeatureBitset &Features_) : Features(Features_) {}
+ MipsAssemblerOptions(const FeatureBitset &Features_) :
+ ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
ATReg = Opts->getATRegIndex();
@@ -108,13 +82,12 @@ public:
static const FeatureBitset AllArchRelatedMask;
private:
- unsigned ATReg = 1;
- bool Reorder = true;
- bool Macro = true;
+ unsigned ATReg;
+ bool Reorder;
+ bool Macro;
FeatureBitset Features;
};
-
-} // end anonymous namespace
+}
const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
@@ -128,7 +101,6 @@ const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
};
namespace {
-
class MipsAsmParser : public MCTargetAsmParser {
MipsTargetStreamer &getTargetStreamer() {
MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
@@ -149,21 +121,13 @@ class MipsAsmParser : public MCTargetAsmParser {
/// If true, then CpSaveLocation is a register, otherwise it's an offset.
bool CpSaveLocationIsRegister;
- // Map of register aliases created via the .set directive.
- StringMap<AsmToken> RegisterSets;
-
// Print a warning along with its fix-it message at the given range.
void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
SMRange Range, bool ShowColors = true);
- void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands);
-
#define GET_ASSEMBLER_HEADER
#include "MipsGenAsmMatcher.inc"
- unsigned
- checkEarlyTargetMatchPredicate(MCInst &Inst,
- const OperandVector &Operands) override;
unsigned checkTargetMatchPredicate(MCInst &Inst) override;
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
@@ -178,8 +142,6 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
- bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
-
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
@@ -190,14 +152,14 @@ class MipsAsmParser : public MCTargetAsmParser {
matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
StringRef Identifier, SMLoc S);
OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
- const AsmToken &Token,
- SMLoc S);
- OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
SMLoc S);
OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
OperandMatchResultTy parseImm(OperandVector &Operands);
OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
OperandMatchResultTy parseInvNum(OperandVector &Operands);
+ OperandMatchResultTy parseLSAImm(OperandVector &Operands);
+ OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
+ OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
OperandMatchResultTy parseRegisterList(OperandVector &Operands);
bool searchSymbolAlias(OperandVector &Operands);
@@ -211,109 +173,82 @@ class MipsAsmParser : public MCTargetAsmParser {
};
// Expands assembly pseudo instructions.
- MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ MacroExpanderResultTy
+ tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
- bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
- MCStreamer &Out, const MCSubtargetInfo *STI);
+ SmallVectorImpl<MCInst> &Instructions);
bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
- MCStreamer &Out, const MCSubtargetInfo *STI);
-
- bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym);
+ SmallVectorImpl<MCInst> &Instructions);
bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
- MCStreamer &Out, const MCSubtargetInfo *STI);
-
- bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU,
- SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ SmallVectorImpl<MCInst> &Instructions);
bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
const MCOperand &Offset, bool Is32BitAddress,
- SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
-
- bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
-
- void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, bool IsLoad);
+ SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
- bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
- bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ void expandMemInst(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions, bool isLoad,
+ bool isImmOpnd);
- bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
- bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
- bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, const bool IsMips64,
- const bool Signed);
+ bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
- bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
- MCStreamer &Out, const MCSubtargetInfo *STI);
+ bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
- bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ bool expandDiv(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
+ const bool Signed);
- bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
- bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ bool expandUlw(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
bool expandRotation(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out, const MCSubtargetInfo *STI);
- bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
- bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
- bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
-
- bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
-
- bool expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
-
- bool expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
-
- bool expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
-
- bool expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ SmallVectorImpl<MCInst> &Instructions);
+ bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
+ bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
+ bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
- bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, bool IsLoad);
+ void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
- bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
+ bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
- bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
-
- bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
bool reportParseError(Twine ErrorMsg);
bool reportParseError(SMLoc Loc, Twine ErrorMsg);
bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
+ bool parseRelocOperand(const MCExpr *&Res);
+
+ const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
bool isEvaluated(const MCExpr *Expr);
bool parseSetMips0Directive();
@@ -328,8 +263,6 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseDirectiveSet();
bool parseDirectiveOption();
bool parseInsnDirective();
- bool parseRSectionDirective(StringRef Section);
- bool parseSSectionDirective(StringRef Section, unsigned Type);
bool parseSetAtDirective();
bool parseSetNoAtDirective();
@@ -349,20 +282,12 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseSetPushDirective();
bool parseSetSoftFloatDirective();
bool parseSetHardFloatDirective();
- bool parseSetMtDirective();
- bool parseSetNoMtDirective();
- bool parseSetNoCRCDirective();
- bool parseSetNoVirtDirective();
- bool parseSetNoGINVDirective();
bool parseSetAssignment();
+ bool parseDataDirective(unsigned Size, SMLoc L);
bool parseDirectiveGpWord();
bool parseDirectiveGpDWord();
- bool parseDirectiveDtpRelWord();
- bool parseDirectiveDtpRelDWord();
- bool parseDirectiveTpRelWord();
- bool parseDirectiveTpRelDWord();
bool parseDirectiveModule();
bool parseDirectiveModuleFP();
bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
@@ -370,12 +295,16 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseInternalDirectiveReallowModule();
+ MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
+
bool eatComma(StringRef ErrorStr);
int matchCPURegisterName(StringRef Symbol);
int matchHWRegsRegisterName(StringRef Symbol);
+ int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
+
int matchFPURegisterName(StringRef Name);
int matchFCCRegisterName(StringRef Name);
@@ -388,15 +317,15 @@ class MipsAsmParser : public MCTargetAsmParser {
unsigned getReg(int RC, int RegNo);
+ unsigned getGPR(int RegNo);
+
/// Returns the internal register number for the current AT. Also checks if
/// the current AT is unavailable (set to $0) and gives an error if it is.
/// This should be used in pseudo-instruction expansions which need AT.
unsigned getATReg(SMLoc Loc);
- bool canUseATReg();
-
- bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI);
+ bool processInstruction(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
// Helper function that checks if the value of a vector index is within the
// boundaries of accepted values for each RegisterKind
@@ -466,15 +395,6 @@ class MipsAsmParser : public MCTargetAsmParser {
public:
enum MipsMatchResultTy {
Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
- Match_RequiresDifferentOperands,
- Match_RequiresNoZeroRegister,
- Match_RequiresSameSrcAndDst,
- Match_NoFCCRegisterForCurrentISA,
- Match_NonZeroOperandForSync,
- Match_NonZeroOperandForMTCX,
- Match_RequiresPosSizeRange0_32,
- Match_RequiresPosSizeRange33_64,
- Match_RequiresPosSizeUImm6,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "MipsGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
@@ -482,15 +402,12 @@ public:
MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
const MCInstrInfo &MII, const MCTargetOptions &Options)
- : MCTargetAsmParser(Options, sti, MII),
+ : MCTargetAsmParser(Options, sti),
ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
sti.getCPU(), Options)) {
MCAsmParserExtension::Initialize(parser);
parser.addAliasForDirective(".asciiz", ".asciz");
- parser.addAliasForDirective(".hword", ".2byte");
- parser.addAliasForDirective(".word", ".4byte");
- parser.addAliasForDirective(".dword", ".8byte");
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
@@ -510,19 +427,18 @@ public:
CurrentFn = nullptr;
- IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
+ IsPicEnabled =
+ (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
IsCpRestoreSet = false;
CpRestoreOffset = -1;
- const Triple &TheTriple = sti.getTargetTriple();
- IsLittleEndian = TheTriple.isLittleEndian();
-
- if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode())
- report_fatal_error("microMIPS64R6 is not supported", false);
-
- if (!isABI_O32() && inMicroMipsMode())
- report_fatal_error("microMIPS64 is not supported", false);
+ Triple TheTriple(sti.getTargetTriple());
+ if ((TheTriple.getArch() == Triple::mips) ||
+ (TheTriple.getArch() == Triple::mips64))
+ IsLittleEndian = false;
+ else
+ IsLittleEndian = true;
}
/// True if all of $fcc0 - $fcc7 exist for the current ISA.
@@ -531,11 +447,9 @@ public:
bool isGP64bit() const {
return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
}
-
bool isFP64bit() const {
return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
}
-
const MipsABIInfo &getABI() const { return ABI; }
bool isABI_N32() const { return ABI.IsN32(); }
bool isABI_N64() const { return ABI.IsN64(); }
@@ -551,63 +465,48 @@ public:
bool inMicroMipsMode() const {
return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
}
-
bool hasMips1() const {
return getSTI().getFeatureBits()[Mips::FeatureMips1];
}
-
bool hasMips2() const {
return getSTI().getFeatureBits()[Mips::FeatureMips2];
}
-
bool hasMips3() const {
return getSTI().getFeatureBits()[Mips::FeatureMips3];
}
-
bool hasMips4() const {
return getSTI().getFeatureBits()[Mips::FeatureMips4];
}
-
bool hasMips5() const {
return getSTI().getFeatureBits()[Mips::FeatureMips5];
}
-
bool hasMips32() const {
return getSTI().getFeatureBits()[Mips::FeatureMips32];
}
-
bool hasMips64() const {
return getSTI().getFeatureBits()[Mips::FeatureMips64];
}
-
bool hasMips32r2() const {
return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
}
-
bool hasMips64r2() const {
return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
}
-
bool hasMips32r3() const {
return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
}
-
bool hasMips64r3() const {
return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
}
-
bool hasMips32r5() const {
return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
}
-
bool hasMips64r5() const {
return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
}
-
bool hasMips32r6() const {
return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
}
-
bool hasMips64r6() const {
return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
}
@@ -615,19 +514,15 @@ public:
bool hasDSP() const {
return getSTI().getFeatureBits()[Mips::FeatureDSP];
}
-
bool hasDSPR2() const {
return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
}
-
bool hasDSPR3() const {
return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
}
-
bool hasMSA() const {
return getSTI().getFeatureBits()[Mips::FeatureMSA];
}
-
bool hasCnMips() const {
return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
}
@@ -647,21 +542,6 @@ public:
bool useSoftFloat() const {
return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
}
- bool hasMT() const {
- return getSTI().getFeatureBits()[Mips::FeatureMT];
- }
-
- bool hasCRC() const {
- return getSTI().getFeatureBits()[Mips::FeatureCRC];
- }
-
- bool hasVirt() const {
- return getSTI().getFeatureBits()[Mips::FeatureVirt];
- }
-
- bool hasGINV() const {
- return getSTI().getFeatureBits()[Mips::FeatureGINV];
- }
/// Warn if RegIndex is the same as the current AT.
void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
@@ -669,65 +549,10 @@ public:
void warnIfNoMacro(SMLoc Loc);
bool isLittle() const { return IsLittleEndian; }
-
- const MCExpr *createTargetUnaryExpr(const MCExpr *E,
- AsmToken::TokenKind OperatorToken,
- MCContext &Ctx) override {
- switch(OperatorToken) {
- default:
- llvm_unreachable("Unknown token");
- return nullptr;
- case AsmToken::PercentCall16:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
- case AsmToken::PercentCall_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
- case AsmToken::PercentCall_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
- case AsmToken::PercentDtprel_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
- case AsmToken::PercentDtprel_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
- case AsmToken::PercentGot:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
- case AsmToken::PercentGot_Disp:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
- case AsmToken::PercentGot_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
- case AsmToken::PercentGot_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
- case AsmToken::PercentGot_Ofst:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
- case AsmToken::PercentGot_Page:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
- case AsmToken::PercentGottprel:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
- case AsmToken::PercentGp_Rel:
- return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
- case AsmToken::PercentHi:
- return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
- case AsmToken::PercentHigher:
- return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
- case AsmToken::PercentHighest:
- return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
- case AsmToken::PercentLo:
- return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
- case AsmToken::PercentNeg:
- return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
- case AsmToken::PercentPcrel_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
- case AsmToken::PercentPcrel_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
- case AsmToken::PercentTlsgd:
- return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
- case AsmToken::PercentTlsldm:
- return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
- case AsmToken::PercentTprel_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
- case AsmToken::PercentTprel_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
- }
- }
};
+}
+
+namespace {
/// MipsOperand - Instances of this class represent a parsed Mips machine
/// instruction.
@@ -759,30 +584,17 @@ private:
enum KindTy {
k_Immediate, /// An immediate (possibly involving symbol references)
k_Memory, /// Base + Offset Memory Address
+ k_PhysRegister, /// A physical register from the Mips namespace
k_RegisterIndex, /// A register index in one or more RegKind.
k_Token, /// A simple token
k_RegList, /// A physical register list
+ k_RegPair /// A pair of physical register
} Kind;
public:
MipsOperand(KindTy K, MipsAsmParser &Parser)
: MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
- ~MipsOperand() override {
- switch (Kind) {
- case k_Memory:
- delete Mem.Base;
- break;
- case k_RegList:
- delete RegList.List;
- break;
- case k_Immediate:
- case k_RegisterIndex:
- case k_Token:
- break;
- }
- }
-
private:
/// For diagnostics, and checking the assembler temporary
MipsAsmParser &AsmParser;
@@ -792,10 +604,13 @@ private:
unsigned Length;
};
+ struct PhysRegOp {
+ unsigned Num; /// Register Number
+ };
+
struct RegIdxOp {
unsigned Index; /// Index into the register class
RegKind Kind; /// Bitfield of the kinds it could possibly be
- struct Token Tok; /// The input token this operand originated from.
const MCRegisterInfo *RegInfo;
};
@@ -814,6 +629,7 @@ private:
union {
struct Token Tok;
+ struct PhysRegOp PhysReg;
struct RegIdxOp RegIdx;
struct ImmOp Imm;
struct MemOp Mem;
@@ -823,17 +639,14 @@ private:
SMLoc StartLoc, EndLoc;
/// Internal constructor for register kinds
- static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
- RegKind RegKind,
+ static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
const MCRegisterInfo *RegInfo,
SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
- auto Op = llvm::make_unique<MipsOperand>(k_RegisterIndex, Parser);
+ auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Op->RegIdx.Index = Index;
Op->RegIdx.RegInfo = RegInfo;
Op->RegIdx.Kind = RegKind;
- Op->RegIdx.Tok.Data = Str.data();
- Op->RegIdx.Tok.Length = Str.size();
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
@@ -1008,16 +821,6 @@ public:
/// Render the operand to an MCInst as a GPR32
/// Asserts if the wrong number of operands are requested, or the operand
/// is not a k_RegisterIndex compatible with RegKind_GPR
- void addGPR32ZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
- }
-
- void addGPR32NonZeroAsmRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
- }
-
void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
@@ -1038,17 +841,6 @@ public:
Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
}
- void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
- }
-
- void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst,
- unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
- }
-
/// Render the operand to an MCInst as a GPR64
/// Asserts if the wrong number of operands are requested, or the operand
/// is not a k_RegisterIndex compatible with RegKind_GPR
@@ -1062,16 +854,6 @@ public:
Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
}
- void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
- }
-
- void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
- }
-
void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
@@ -1081,17 +863,6 @@ public:
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
// FIXME: We ought to do this for -integrated-as without -via-file-asm too.
- // FIXME: This should propagate failure up to parseStatement.
- if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
- AsmParser.getParser().printError(
- StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
- "registers");
- }
-
- void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
- // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
"registers");
@@ -1161,35 +932,7 @@ public:
void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
uint64_t Imm = getConstantImm() - Offset;
- Imm &= (1ULL << Bits) - 1;
- Imm += Offset;
- Imm += AdjustOffset;
- Inst.addOperand(MCOperand::createImm(Imm));
- }
-
- template <unsigned Bits>
- void addSImmOperands(MCInst &Inst, unsigned N) const {
- if (isImm() && !isConstantImm()) {
- addExpr(Inst, getImm());
- return;
- }
- addConstantSImmOperands<Bits, 0, 0>(Inst, N);
- }
-
- template <unsigned Bits>
- void addUImmOperands(MCInst &Inst, unsigned N) const {
- if (isImm() && !isConstantImm()) {
- addExpr(Inst, getImm());
- return;
- }
- addConstantUImmOperands<Bits, 0, 0>(Inst, N);
- }
-
- template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
- void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
- assert(N == 1 && "Invalid number of operands!");
- int64_t Imm = getConstantImm() - Offset;
- Imm = SignExtend64<Bits>(Imm);
+ Imm &= (1 << Bits) - 1;
Imm += Offset;
Imm += AdjustOffset;
Inst.addOperand(MCOperand::createImm(Imm));
@@ -1228,136 +971,75 @@ public:
Inst.addOperand(MCOperand::createReg(RegNo));
}
- bool isReg() const override {
- // As a special case until we sort out the definition of div/divu, accept
- // $0/$zero here so that MCK_ZERO works correctly.
- return isGPRAsmReg() && RegIdx.Index == 0;
+ void addRegPairOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ unsigned RegNo = getRegPair();
+ Inst.addOperand(MCOperand::createReg(RegNo++));
+ Inst.addOperand(MCOperand::createReg(RegNo));
}
+ void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+ for (auto RegNo : getRegList())
+ Inst.addOperand(MCOperand::createReg(RegNo));
+ }
+
+ bool isReg() const override {
+ // 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 override { return Kind == k_Immediate; }
-
bool isConstantImm() const {
- int64_t Res;
- return isImm() && getImm()->evaluateAsAbsolute(Res);
+ return isImm() && isa<MCConstantExpr>(getImm());
}
-
bool isConstantImmz() const {
return isConstantImm() && getConstantImm() == 0;
}
-
template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
}
-
- template <unsigned Bits> bool isSImm() const {
- return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
- }
-
- template <unsigned Bits> bool isUImm() const {
- return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
- }
-
- template <unsigned Bits> bool isAnyImm() const {
- return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
- isUInt<Bits>(getConstantImm()))
- : isImm();
- }
-
- template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
- return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
+ template <unsigned Bits> bool isConstantSImm() const {
+ return isConstantImm() && isInt<Bits>(getConstantImm());
}
-
- template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
- return isConstantImm() && getConstantImm() >= Bottom &&
- getConstantImm() <= Top;
- }
-
bool isToken() const override {
// 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 override { return Kind == k_Memory; }
-
bool isConstantMemOff() const {
return isMem() && isa<MCConstantExpr>(getMemOff());
}
-
- // Allow relocation operators.
- // FIXME: This predicate and others need to look through binary expressions
- // and determine whether a Value is a constant or not.
- template <unsigned Bits, unsigned ShiftAmount = 0>
- bool isMemWithSimmOffset() const {
- if (!isMem())
- return false;
- if (!getMemBase()->isGPRAsmReg())
- return false;
- if (isa<MCTargetExpr>(getMemOff()) ||
- (isConstantMemOff() &&
- isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
- return true;
- MCValue Res;
- bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
- return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
+ template <unsigned Bits> bool isMemWithSimmOffset() const {
+ return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
+ && getMemBase()->isGPRAsmReg();
}
-
- bool isMemWithPtrSizeOffset() const {
- if (!isMem())
- return false;
- if (!getMemBase()->isGPRAsmReg())
- return false;
- const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
- if (isa<MCTargetExpr>(getMemOff()) ||
- (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
- return true;
- MCValue Res;
- bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
- return IsReloc && isIntN(PtrBits, Res.getConstant());
+ template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
+ return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
+ getMemBase()->isGPRAsmReg();
}
-
bool isMemWithGRPMM16Base() const {
return isMem() && getMemBase()->isMM16AsmReg();
}
-
template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
&& getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
}
-
template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
&& (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
&& (getMemBase()->getGPR32Reg() == Mips::SP);
}
-
- template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
- return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
- && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
- && (getMemBase()->getGPR32Reg() == Mips::GP);
- }
-
template <unsigned Bits, unsigned ShiftLeftAmount>
bool isScaledUImm() const {
return isConstantImm() &&
isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
}
-
- template <unsigned Bits, unsigned ShiftLeftAmount>
- bool isScaledSImm() const {
- if (isConstantImm() &&
- isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
- return true;
- // Operand can also be a symbol or symbol plus
- // offset in case of relocations.
- if (Kind != k_Immediate)
- return false;
- MCValue Res;
- bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
- return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
- }
-
bool isRegList16() const {
if (!isRegList())
return false;
@@ -1382,32 +1064,49 @@ public:
return true;
}
-
bool isInvNum() const { return Kind == k_Immediate; }
-
bool isLSAImm() const {
if (!isConstantImm())
return false;
int64_t Val = getConstantImm();
return 1 <= Val && Val <= 4;
}
-
bool isRegList() const { return Kind == k_RegList; }
+ bool isMovePRegPair() const {
+ if (Kind != k_RegList || RegList.List->size() != 2)
+ return false;
+
+ unsigned R0 = RegList.List->front();
+ unsigned R1 = RegList.List->back();
+
+ if ((R0 == Mips::A1 && R1 == Mips::A2) ||
+ (R0 == Mips::A1 && R1 == Mips::A3) ||
+ (R0 == Mips::A2 && R1 == Mips::A3) ||
+ (R0 == Mips::A0 && R1 == Mips::S5) ||
+ (R0 == Mips::A0 && R1 == Mips::S6) ||
+ (R0 == Mips::A0 && R1 == Mips::A1) ||
+ (R0 == Mips::A0 && R1 == Mips::A2) ||
+ (R0 == Mips::A0 && R1 == Mips::A3))
+ return true;
+
+ return false;
+ }
StringRef getToken() const {
assert(Kind == k_Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
}
+ bool isRegPair() const { return Kind == k_RegPair; }
unsigned getReg() const override {
- // As a special case until we sort out the definition of div/divu, accept
- // $0/$zero here so that MCK_ZERO works correctly.
+ // 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
- llvm_unreachable("Invalid access!");
- return 0;
+ assert(Kind == k_PhysRegister && "Invalid access!");
+ return PhysReg.Num;
}
const MCExpr *getImm() const {
@@ -1417,9 +1116,7 @@ public:
int64_t getConstantImm() const {
const MCExpr *Val = getImm();
- int64_t Value = 0;
- (void)Val->evaluateAsAbsolute(Value);
- return Value;
+ return static_cast<const MCConstantExpr *>(Val)->getValue();
}
MipsOperand *getMemBase() const {
@@ -1441,9 +1138,14 @@ public:
return *(RegList.List);
}
+ unsigned getRegPair() const {
+ assert((Kind == k_RegPair) && "Invalid access!");
+ return RegIdx.Index;
+ }
+
static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
MipsAsmParser &Parser) {
- auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
+ auto Op = make_unique<MipsOperand>(k_Token, Parser);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
@@ -1454,71 +1156,71 @@ public:
/// Create a numeric register (e.g. $1). The exact register remains
/// unresolved until an instruction successfully matches
static std::unique_ptr<MipsOperand>
- createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
- SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
- return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
+ createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
+ return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
}
/// Create a register that is definitely a GPR.
/// This is typically only used for named registers such as $gp.
static std::unique_ptr<MipsOperand>
- createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
- SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
+ createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
+ MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
}
/// Create a register that is definitely a FGR.
/// This is typically only used for named registers such as $f0.
static std::unique_ptr<MipsOperand>
- createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
- SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
+ createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
+ MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
}
/// Create a register that is definitely a HWReg.
/// This is typically only used for named registers such as $hwr_cpunum.
static std::unique_ptr<MipsOperand>
- createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
+ createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
+ return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
}
/// Create a register that is definitely an FCC.
/// This is typically only used for named registers such as $fcc0.
static std::unique_ptr<MipsOperand>
- createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
- SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
+ 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 std::unique_ptr<MipsOperand>
- createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
- SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
+ 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 std::unique_ptr<MipsOperand>
- createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
- SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
+ 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 std::unique_ptr<MipsOperand>
- createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
- SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
+ createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
+ SMLoc E, MipsAsmParser &Parser) {
+ return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
}
static std::unique_ptr<MipsOperand>
CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
- auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser);
+ auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
@@ -1528,7 +1230,7 @@ public:
static std::unique_ptr<MipsOperand>
CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
- auto Op = llvm::make_unique<MipsOperand>(k_Memory, Parser);
+ auto Op = make_unique<MipsOperand>(k_Memory, Parser);
Op->Mem.Base = Base.release();
Op->Mem.Off = Off;
Op->StartLoc = S;
@@ -1539,34 +1241,32 @@ public:
static std::unique_ptr<MipsOperand>
CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
MipsAsmParser &Parser) {
- assert(Regs.size() > 0 && "Empty list not allowed");
+ assert (Regs.size() > 0 && "Empty list not allowed");
- auto Op = llvm::make_unique<MipsOperand>(k_RegList, Parser);
+ auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Op->StartLoc = StartLoc;
Op->EndLoc = EndLoc;
return Op;
}
- bool isGPRZeroAsmReg() const {
- return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0;
- }
-
- bool isGPRNonZeroAsmReg() const {
- return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index > 0 &&
- RegIdx.Index <= 31;
+ static std::unique_ptr<MipsOperand>
+ CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
+ auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
+ Op->RegIdx.Index = RegNo;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
}
bool isGPRAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
}
-
bool isMM16AsmReg() const {
if (!(isRegIdx() && RegIdx.Kind))
return false;
return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
|| RegIdx.Index == 16 || RegIdx.Index == 17);
-
}
bool isMM16AsmRegZero() const {
if (!(isRegIdx() && RegIdx.Kind))
@@ -1575,71 +1275,44 @@ public:
(RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
RegIdx.Index == 17);
}
-
bool isMM16AsmRegMoveP() const {
if (!(isRegIdx() && RegIdx.Kind))
return false;
return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
(RegIdx.Index >= 16 && RegIdx.Index <= 20));
}
-
- bool isMM16AsmRegMovePPairFirst() const {
- if (!(isRegIdx() && RegIdx.Kind))
- return false;
- return RegIdx.Index >= 4 && RegIdx.Index <= 6;
- }
-
- bool isMM16AsmRegMovePPairSecond() const {
- if (!(isRegIdx() && RegIdx.Kind))
- return false;
- return (RegIdx.Index == 21 || RegIdx.Index == 22 ||
- (RegIdx.Index >= 5 && RegIdx.Index <= 7));
- }
-
bool isFGRAsmReg() const {
// AFGR64 is $0-$15 but we handle this in getAFGR64()
return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
}
-
- bool isStrictlyFGRAsmReg() const {
- // AFGR64 is $0-$15 but we handle this in getAFGR64()
- return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31;
- }
-
bool isHWRegsAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
}
-
bool isCCRAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
}
-
bool isFCCAsmReg() const {
if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
return false;
+ if (!AsmParser.hasEightFccRegisters())
+ return RegIdx.Index == 0;
return RegIdx.Index <= 7;
}
-
bool isACCAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
}
-
bool isCOP0AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
}
-
bool isCOP2AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
}
-
bool isCOP3AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
}
-
bool isMSA128AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
}
-
bool isMSACtrlAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
}
@@ -1649,6 +1322,23 @@ public:
/// getEndLoc - Get the location of the last token of this operand.
SMLoc getEndLoc() const override { return EndLoc; }
+ virtual ~MipsOperand() {
+ switch (Kind) {
+ case k_Immediate:
+ break;
+ case k_Memory:
+ delete Mem.Base;
+ break;
+ case k_RegList:
+ delete RegList.List;
+ case k_PhysRegister:
+ case k_RegisterIndex:
+ case k_Token:
+ case k_RegPair:
+ break;
+ }
+ }
+
void print(raw_ostream &OS) const override {
switch (Kind) {
case k_Immediate:
@@ -1663,12 +1353,14 @@ public:
OS << *Mem.Off;
OS << ">";
break;
+ case k_PhysRegister:
+ OS << "PhysReg<" << PhysReg.Num << ">";
+ break;
case k_RegisterIndex:
- OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
- << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
+ OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
break;
case k_Token:
- OS << getToken();
+ OS << Tok.Data;
break;
case k_RegList:
OS << "RegList< ";
@@ -1676,55 +1368,29 @@ public:
OS << Reg << " ";
OS << ">";
break;
- }
- }
-
- bool isValidForTie(const MipsOperand &Other) const {
- if (Kind != Other.Kind)
- return false;
-
- switch (Kind) {
- default:
- llvm_unreachable("Unexpected kind");
- return false;
- case k_RegisterIndex: {
- StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
- StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
- return Token == OtherToken;
- }
+ case k_RegPair:
+ OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
+ break;
}
}
}; // class MipsOperand
-
-} // end anonymous namespace
+} // namespace
namespace llvm {
-
extern const MCInstrDesc MipsInsts[];
-
-} // end namespace llvm
-
+}
static const MCInstrDesc &getInstDesc(unsigned Opcode) {
return MipsInsts[Opcode];
}
-static bool hasShortDelaySlot(MCInst &Inst) {
- switch (Inst.getOpcode()) {
- case Mips::BEQ_MM:
- case Mips::BNE_MM:
- case Mips::BLTZ_MM:
- case Mips::BGEZ_MM:
- case Mips::BLEZ_MM:
- case Mips::BGTZ_MM:
- case Mips::JRC16_MM:
+static bool hasShortDelaySlot(unsigned Opcode) {
+ switch (Opcode) {
case Mips::JALS_MM:
case Mips::JALRS_MM:
case Mips::JALRS16_MM:
case Mips::BGEZALS_MM:
case Mips::BLTZALS_MM:
return true;
- case Mips::J_MM:
- return !Inst.getOperand(0).isReg();
default:
return false;
}
@@ -1768,10 +1434,83 @@ static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
return 0;
}
+namespace {
+void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ MCInst tmpInst;
+ tmpInst.setOpcode(Opcode);
+ tmpInst.addOperand(MCOperand::createReg(Reg0));
+ tmpInst.addOperand(Op1);
+ tmpInst.setLoc(IDLoc);
+ Instructions.push_back(tmpInst);
+}
+
+void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
+}
+
+void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
+}
+
+void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ MCInst tmpInst;
+ tmpInst.setOpcode(Opcode);
+ tmpInst.addOperand(MCOperand::createImm(Imm1));
+ tmpInst.addOperand(MCOperand::createImm(Imm2));
+ tmpInst.setLoc(IDLoc);
+ Instructions.push_back(tmpInst);
+}
+
+void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ MCInst tmpInst;
+ tmpInst.setOpcode(Opcode);
+ tmpInst.addOperand(MCOperand::createReg(Reg0));
+ tmpInst.setLoc(IDLoc);
+ Instructions.push_back(tmpInst);
+}
+
+void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
+ SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
+ MCInst tmpInst;
+ tmpInst.setOpcode(Opcode);
+ tmpInst.addOperand(MCOperand::createReg(Reg0));
+ tmpInst.addOperand(MCOperand::createReg(Reg1));
+ tmpInst.addOperand(Op2);
+ tmpInst.setLoc(IDLoc);
+ Instructions.push_back(tmpInst);
+}
+
+void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
+ SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
+ emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
+ Instructions);
+}
+
+void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
+ SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
+ emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
+ Instructions);
+}
+
+void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
+ SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
+ if (ShiftAmount >= 32) {
+ emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
+ Instructions);
+ return;
+ }
+
+ emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
+}
+} // end anonymous namespace.
+
bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
+ SmallVectorImpl<MCInst> &Instructions) {
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
bool ExpandedJalSym = false;
@@ -1789,7 +1528,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case Mips::BBIT1:
case Mips::BBIT132:
assert(hasCnMips() && "instruction only valid for octeon cpus");
- LLVM_FALLTHROUGH;
+ // Fall through
case Mips::BEQ:
case Mips::BNE:
@@ -1821,10 +1560,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case Mips::BLTZAL_MM:
case Mips::BC1F_MM:
case Mips::BC1T_MM:
- case Mips::BC1EQZC_MMR6:
- case Mips::BC1NEZC_MMR6:
- case Mips::BC2EQZC_MMR6:
- case Mips::BC2NEZC_MMR6:
assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Offset = Inst.getOperand(1);
if (!Offset.isImm())
@@ -1835,45 +1570,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1LL << (inMicroMipsMode() ? 1 : 2)))
return Error(IDLoc, "branch to misaligned address");
break;
- case Mips::BGEC: case Mips::BGEC_MMR6:
- case Mips::BLTC: case Mips::BLTC_MMR6:
- case Mips::BGEUC: case Mips::BGEUC_MMR6:
- case Mips::BLTUC: case Mips::BLTUC_MMR6:
- case Mips::BEQC: case Mips::BEQC_MMR6:
- case Mips::BNEC: case Mips::BNEC_MMR6:
- assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
- Offset = Inst.getOperand(2);
- if (!Offset.isImm())
- break; // We'll deal with this situation later on when applying fixups.
- if (!isIntN(18, Offset.getImm()))
- return Error(IDLoc, "branch target out of range");
- if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
- return Error(IDLoc, "branch to misaligned address");
- break;
- case Mips::BLEZC: case Mips::BLEZC_MMR6:
- case Mips::BGEZC: case Mips::BGEZC_MMR6:
- case Mips::BGTZC: case Mips::BGTZC_MMR6:
- case Mips::BLTZC: case Mips::BLTZC_MMR6:
- assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
- Offset = Inst.getOperand(1);
- if (!Offset.isImm())
- break; // We'll deal with this situation later on when applying fixups.
- if (!isIntN(18, Offset.getImm()))
- return Error(IDLoc, "branch target out of range");
- if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
- return Error(IDLoc, "branch to misaligned address");
- break;
- case Mips::BEQZC: case Mips::BEQZC_MMR6:
- case Mips::BNEZC: case Mips::BNEZC_MMR6:
- assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
- Offset = Inst.getOperand(1);
- if (!Offset.isImm())
- break; // We'll deal with this situation later on when applying fixups.
- if (!isIntN(23, Offset.getImm()))
- return Error(IDLoc, "branch target out of range");
- if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
- return Error(IDLoc, "branch to misaligned address");
- break;
case Mips::BEQZ16_MM:
case Mips::BEQZC16_MMR6:
case Mips::BNEZ16_MM:
@@ -1940,71 +1636,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
}
}
- // Warn on division by zero. We're checking here as all instructions get
- // processed here, not just the macros that need expansion.
- //
- // The MIPS backend models most of the divison instructions and macros as
- // three operand instructions. The pre-R6 divide instructions however have
- // two operands and explicitly define HI/LO as part of the instruction,
- // not in the operands.
- unsigned FirstOp = 1;
- unsigned SecondOp = 2;
- switch (Inst.getOpcode()) {
- default:
- break;
- case Mips::SDivIMacro:
- case Mips::UDivIMacro:
- case Mips::DSDivIMacro:
- case Mips::DUDivIMacro:
- if (Inst.getOperand(2).getImm() == 0) {
- if (Inst.getOperand(1).getReg() == Mips::ZERO ||
- Inst.getOperand(1).getReg() == Mips::ZERO_64)
- Warning(IDLoc, "dividing zero by zero");
- else
- Warning(IDLoc, "division by zero");
- }
- break;
- case Mips::DSDIV:
- case Mips::SDIV:
- case Mips::UDIV:
- case Mips::DUDIV:
- case Mips::UDIV_MM:
- case Mips::SDIV_MM:
- FirstOp = 0;
- SecondOp = 1;
- LLVM_FALLTHROUGH;
- case Mips::SDivMacro:
- case Mips::DSDivMacro:
- case Mips::UDivMacro:
- case Mips::DUDivMacro:
- case Mips::DIV:
- case Mips::DIVU:
- case Mips::DDIV:
- case Mips::DDIVU:
- case Mips::DIVU_MMR6:
- case Mips::DIV_MMR6:
- if (Inst.getOperand(SecondOp).getReg() == Mips::ZERO ||
- Inst.getOperand(SecondOp).getReg() == Mips::ZERO_64) {
- if (Inst.getOperand(FirstOp).getReg() == Mips::ZERO ||
- Inst.getOperand(FirstOp).getReg() == Mips::ZERO_64)
- Warning(IDLoc, "dividing zero by zero");
- else
- Warning(IDLoc, "division by zero");
- }
- break;
- }
-
- // For PIC code convert unconditional jump to unconditional branch.
- if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
- inPicMode()) {
- MCInst BInst;
- BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
- BInst.addOperand(MCOperand::createReg(Mips::ZERO));
- BInst.addOperand(MCOperand::createReg(Mips::ZERO));
- BInst.addOperand(Inst.getOperand(0));
- Inst = BInst;
- }
-
// This expansion is not in a function called by tryExpandInstruction()
// because the pseudo-instruction doesn't have a distinct opcode.
if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
@@ -2019,15 +1650,15 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
// FIXME: This is checking the expression can be handled by the later stages
- // of the assembler. We ought to leave it to those later stages.
+ // of the assembler. We ought to leave it to those later stages but
+ // we can't do that until we stop evaluateRelocExpr() rewriting the
+ // expressions into non-equivalent forms.
const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
// FIXME: Add support for label+offset operands (currently causes an error).
// FIXME: Add support for forward-declared local symbols.
// FIXME: Add expansion for when the LargeGOT option is enabled.
- if (JalSym->isInSection() || JalSym->isTemporary() ||
- (JalSym->isELF() &&
- cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
+ if (JalSym->isInSection() || JalSym->isTemporary()) {
if (isABI_O32()) {
// If it's a local symbol and the O32 ABI is being used, we expand to:
// lw $25, 0($gp)
@@ -2035,38 +1666,33 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// addiu $25, $25, 0
// R_(MICRO)MIPS_LO16 label
// jalr $25
- const MCExpr *Got16RelocExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
- const MCExpr *Lo16RelocExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
-
- TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
- MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
- TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
- MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
+ const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
+ const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
+
+ emitRRX(Mips::LW, Mips::T9, Mips::GP,
+ MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
+ emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
+ MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
} else if (isABI_N32() || isABI_N64()) {
// If it's a local symbol and the N32/N64 ABIs are being used,
// we expand to:
// lw/ld $25, 0($gp)
// R_(MICRO)MIPS_GOT_DISP label
// jalr $25
- const MCExpr *GotDispRelocExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
+ const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
- TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
- Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
- STI);
+ emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
+ MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
}
} else {
// If it's an external/weak symbol, we expand to:
// lw/ld $25, 0($gp)
// R_(MICRO)MIPS_CALL16 label
// jalr $25
- const MCExpr *Call16RelocExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
+ const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
- TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
- MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
+ emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
+ MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
}
MCInst JalrInst;
@@ -2077,28 +1703,15 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
JalrInst.addOperand(MCOperand::createReg(Mips::RA));
JalrInst.addOperand(MCOperand::createReg(Mips::T9));
- if (EmitJalrReloc) {
- // As an optimization hint for the linker, before the JALR we add:
- // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
- // tmplabel:
- MCSymbol *TmpLabel = getContext().createTempSymbol();
- const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());
- const MCExpr *RelocJalrExpr =
- MCSymbolRefExpr::create(JalSym, MCSymbolRefExpr::VK_None,
- getContext(), IDLoc);
-
- TOut.getStreamer().EmitRelocDirective(*TmpExpr,
- inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
- RelocJalrExpr, IDLoc, *STI);
- TOut.getStreamer().EmitLabel(TmpLabel);
- }
+ // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
+ // This relocation is supposed to be an optimization hint for the linker
+ // and is not necessary for correctness.
Inst = JalrInst;
ExpandedJalSym = true;
}
- bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
- if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
+ if (MCID.mayLoad() || MCID.mayStore()) {
// Check the offset of memory operand, if it is a symbol
// reference or immediate we may have to expand instructions.
for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
@@ -2107,11 +1720,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
(OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
MCOperand &Op = Inst.getOperand(i);
if (Op.isImm()) {
- int64_t MemOffset = Op.getImm();
+ int MemOffset = Op.getImm();
if (MemOffset < -32768 || MemOffset > 32767) {
// Offset can't exceed 16bit value.
- expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
- return getParser().hasPendingError();
+ expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
+ return false;
}
} else if (Op.isExpr()) {
const MCExpr *Expr = Op.getExpr();
@@ -2120,12 +1733,12 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
static_cast<const MCSymbolRefExpr *>(Expr);
if (SR->getKind() == MCSymbolRefExpr::VK_None) {
// Expand symbol.
- expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
- return getParser().hasPendingError();
+ expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
+ return false;
}
} else if (!isEvaluated(Expr)) {
- expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
- return getParser().hasPendingError();
+ expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
+ return false;
}
}
}
@@ -2133,7 +1746,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
} // if load/store
if (inMicroMipsMode()) {
- if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) {
+ if (MCID.mayLoad()) {
// Try to create 16-bit GP relative load instruction.
for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
const MCOperandInfo &OpInfo = MCID.OpInfo[i];
@@ -2150,8 +1763,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
(BaseReg.getReg() == Mips::GP ||
BaseReg.getReg() == Mips::GP_64)) {
- TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
- IDLoc, STI);
+ emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
+ IDLoc, Instructions);
return false;
}
}
@@ -2167,6 +1780,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
switch (Inst.getOpcode()) {
default:
break;
+ case Mips::ADDIUS5_MM:
+ Opnd = Inst.getOperand(2);
+ if (!Opnd.isImm())
+ return Error(IDLoc, "expected immediate operand kind");
+ Imm = Opnd.getImm();
+ if (Imm < -8 || Imm > 7)
+ return Error(IDLoc, "immediate operand value out of range");
+ break;
case Mips::ADDIUSP_MM:
Opnd = Inst.getOperand(0);
if (!Opnd.isImm())
@@ -2202,6 +1823,16 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
return Error(IDLoc, "immediate operand value out of range");
break;
+ case Mips::ADDIUR1SP_MM:
+ Opnd = Inst.getOperand(1);
+ if (!Opnd.isImm())
+ return Error(IDLoc, "expected immediate operand kind");
+ Imm = Opnd.getImm();
+ if (OffsetToAlignment(Imm, 4LL))
+ return Error(IDLoc, "misaligned immediate operand value");
+ if (Imm < 0 || Imm > 255)
+ return Error(IDLoc, "immediate operand value out of range");
+ break;
case Mips::ANDI16_MM:
Opnd = Inst.getOperand(2);
if (!Opnd.isImm())
@@ -2220,6 +1851,12 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
if (Imm < -1 || Imm > 14)
return Error(IDLoc, "immediate operand value out of range");
break;
+ case Mips::TEQ_MM:
+ case Mips::TGE_MM:
+ case Mips::TGEU_MM:
+ case Mips::TLT_MM:
+ case Mips::TLTU_MM:
+ case Mips::TNE_MM:
case Mips::SB16_MM:
case Mips::SB16_MMR6:
Opnd = Inst.getOperand(2);
@@ -2250,47 +1887,21 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return Error(IDLoc, "immediate operand value out of range");
break;
case Mips::ADDIUPC_MM:
- Opnd = Inst.getOperand(1);
+ MCOperand Opnd = Inst.getOperand(1);
if (!Opnd.isImm())
return Error(IDLoc, "expected immediate operand kind");
- Imm = Opnd.getImm();
+ int Imm = Opnd.getImm();
if ((Imm % 4 != 0) || !isInt<25>(Imm))
return Error(IDLoc, "immediate operand value out of range");
break;
- case Mips::LWP_MM:
- case Mips::SWP_MM:
- if (Inst.getOperand(0).getReg() == Mips::RA)
- return Error(IDLoc, "invalid operand for instruction");
- break;
- case Mips::MOVEP_MM:
- case Mips::MOVEP_MMR6: {
- unsigned R0 = Inst.getOperand(0).getReg();
- unsigned R1 = Inst.getOperand(1).getReg();
- bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) ||
- (R0 == Mips::A1 && R1 == Mips::A3) ||
- (R0 == Mips::A2 && R1 == Mips::A3) ||
- (R0 == Mips::A0 && R1 == Mips::S5) ||
- (R0 == Mips::A0 && R1 == Mips::S6) ||
- (R0 == Mips::A0 && R1 == Mips::A1) ||
- (R0 == Mips::A0 && R1 == Mips::A2) ||
- (R0 == Mips::A0 && R1 == Mips::A3));
- if (!RegPair)
- return Error(IDLoc, "invalid operand for instruction");
- break;
- }
}
}
- bool FillDelaySlot =
- MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
- if (FillDelaySlot)
- TOut.emitDirectiveSetNoReorder();
-
MacroExpanderResultTy ExpandResult =
- tryExpandInstruction(Inst, IDLoc, Out, STI);
+ tryExpandInstruction(Inst, IDLoc, Instructions);
switch (ExpandResult) {
case MER_NotAMacro:
- Out.EmitInstruction(Inst, *STI);
+ Instructions.push_back(Inst);
break;
case MER_Success:
break;
@@ -2298,19 +1909,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return true;
}
- // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
- // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
- if (inMicroMipsMode()) {
- TOut.setUsesMicroMips();
- TOut.updateABIInfo(*this);
- }
-
// If this instruction has a delay slot and .set reorder is active,
// emit a NOP after it.
- if (FillDelaySlot) {
- TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
- TOut.emitDirectiveSetReorder();
- }
+ if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
+ createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
if ((Inst.getOpcode() == Mips::JalOneReg ||
Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
@@ -2320,11 +1922,16 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// If .set reorder has been used, we've already emitted a NOP.
// If .set noreorder has been used, we need to emit a NOP at this point.
if (!AssemblerOptions.back()->isReorder())
- TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc,
- STI);
+ createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
// Load the $gp from the stack.
- TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
+ SmallVector<MCInst, 3> LoadInsts;
+ createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
+ IDLoc, LoadInsts);
+
+ for (const MCInst &Inst : LoadInsts)
+ Instructions.push_back(Inst);
+
} else
Warning(IDLoc, "no .cprestore used in PIC mode");
}
@@ -2333,15 +1940,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
}
MipsAsmParser::MacroExpanderResultTy
-MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
+MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
switch (Inst.getOpcode()) {
default:
return MER_NotAMacro;
case Mips::LoadImm32:
- return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
case Mips::LoadImm64:
- return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
case Mips::LoadAddrImm32:
case Mips::LoadAddrImm64:
assert(Inst.getOperand(0).isReg() && "expected register operand kind");
@@ -2351,7 +1960,7 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
Inst.getOperand(1),
Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
- Out, STI)
+ Instructions)
? MER_Fail
: MER_Success;
case Mips::LoadAddrReg32:
@@ -2364,25 +1973,24 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return expandLoadAddress(Inst.getOperand(0).getReg(),
Inst.getOperand(1).getReg(), Inst.getOperand(2),
Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
- Out, STI)
+ Instructions)
? MER_Fail
: MER_Success;
case Mips::B_MM_Pseudo:
case Mips::B_MMR6_Pseudo:
- return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
- : MER_Success;
+ return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
case Mips::SWM_MM:
case Mips::LWM_MM:
- return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
- : MER_Success;
+ return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
case Mips::JalOneReg:
case Mips::JalTwoReg:
- return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
case Mips::BneImm:
case Mips::BeqImm:
- case Mips::BEQLImmMacro:
- case Mips::BNELImmMacro:
- return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
case Mips::BLT:
case Mips::BLE:
case Mips::BGE:
@@ -2415,163 +2023,75 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
case Mips::BLEULImmMacro:
case Mips::BGEULImmMacro:
case Mips::BGTULImmMacro:
- return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
case Mips::SDivMacro:
- case Mips::SDivIMacro:
- case Mips::SRemMacro:
- case Mips::SRemIMacro:
- return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
+ : MER_Success;
case Mips::DSDivMacro:
- case Mips::DSDivIMacro:
- case Mips::DSRemMacro:
- case Mips::DSRemIMacro:
- return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
+ : MER_Success;
case Mips::UDivMacro:
- case Mips::UDivIMacro:
- case Mips::URemMacro:
- case Mips::URemIMacro:
- return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
+ : MER_Success;
case Mips::DUDivMacro:
- case Mips::DUDivIMacro:
- case Mips::DURemMacro:
- case Mips::DURemIMacro:
- return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
- : MER_Success;
- case Mips::PseudoTRUNC_W_S:
- return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
- : MER_Success;
- case Mips::PseudoTRUNC_W_D32:
- return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
- : MER_Success;
- case Mips::PseudoTRUNC_W_D:
- return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
- : MER_Success;
-
- case Mips::LoadImmSingleGPR:
- return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI)
- ? MER_Fail
- : MER_Success;
- case Mips::LoadImmSingleFGR:
- return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI)
- ? MER_Fail
- : MER_Success;
- case Mips::LoadImmDoubleGPR:
- return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI)
- ? MER_Fail
- : MER_Success;
- case Mips::LoadImmDoubleFGR:
- return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI)
- ? MER_Fail
- : MER_Success;
- case Mips::LoadImmDoubleFGR_32:
- return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI)
- ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
+ : MER_Success;
case Mips::Ulh:
- return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
case Mips::Ulhu:
- return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::Ush:
- return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
case Mips::Ulw:
- case Mips::Usw:
- return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
case Mips::NORImm:
- case Mips::NORImm64:
- return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::SLTImm64:
- if (isInt<16>(Inst.getOperand(2).getImm())) {
- Inst.setOpcode(Mips::SLTi64);
- return MER_NotAMacro;
- }
- return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::SLTUImm64:
- if (isInt<16>(Inst.getOperand(2).getImm())) {
- Inst.setOpcode(Mips::SLTiu64);
- return MER_NotAMacro;
- }
- return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::ADDi: case Mips::ADDi_MM:
- case Mips::ADDiu: case Mips::ADDiu_MM:
- case Mips::SLTi: case Mips::SLTi_MM:
- case Mips::SLTiu: case Mips::SLTiu_MM:
+ return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
+ case Mips::ADDi:
+ case Mips::ADDiu:
+ case Mips::SLTi:
+ case Mips::SLTiu:
if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
int64_t ImmValue = Inst.getOperand(2).getImm();
if (isInt<16>(ImmValue))
return MER_NotAMacro;
- return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
- : MER_Success;
+ return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
}
return MER_NotAMacro;
- case Mips::ANDi: case Mips::ANDi_MM: case Mips::ANDi64:
- case Mips::ORi: case Mips::ORi_MM: case Mips::ORi64:
- case Mips::XORi: case Mips::XORi_MM: case Mips::XORi64:
+ case Mips::ANDi:
+ case Mips::ORi:
+ case Mips::XORi:
if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
int64_t ImmValue = Inst.getOperand(2).getImm();
if (isUInt<16>(ImmValue))
return MER_NotAMacro;
- return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
- : MER_Success;
+ return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
}
return MER_NotAMacro;
case Mips::ROL:
case Mips::ROR:
- return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
case Mips::ROLImm:
case Mips::RORImm:
- return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
case Mips::DROL:
case Mips::DROR:
- return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
case Mips::DROLImm:
case Mips::DRORImm:
- return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::ABSMacro:
- return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::MULImmMacro:
- case Mips::DMULImmMacro:
- return expandMulImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::MULOMacro:
- case Mips::DMULOMacro:
- return expandMulO(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::MULOUMacro:
- case Mips::DMULOUMacro:
- return expandMulOU(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::DMULMacro:
- return expandDMULMacro(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::LDMacro:
- case Mips::SDMacro:
- return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
- Inst.getOpcode() == Mips::LDMacro)
- ? MER_Fail
- : MER_Success;
- case Mips::SEQMacro:
- return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::SEQIMacro:
- return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
- case Mips::MFTC0: case Mips::MTTC0:
- case Mips::MFTGPR: case Mips::MTTGPR:
- case Mips::MFTLO: case Mips::MTTLO:
- case Mips::MFTHI: case Mips::MTTHI:
- case Mips::MFTACX: case Mips::MTTACX:
- case Mips::MFTDSP: case Mips::MTTDSP:
- case Mips::MFTC1: case Mips::MTTC1:
- case Mips::MFTHC1: case Mips::MTTHC1:
- case Mips::CFTC1: case Mips::CTTC1:
- return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
+ : MER_Success;
}
}
bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
-
+ SmallVectorImpl<MCInst> &Instructions) {
// Create a JALR instruction which is going to replace the pseudo-JAL.
MCInst JalrInst;
JalrInst.setLoc(IDLoc);
@@ -2601,14 +2121,14 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
const MCOperand SecondRegOp = Inst.getOperand(1);
JalrInst.addOperand(SecondRegOp);
}
- Out.EmitInstruction(JalrInst, *STI);
+ Instructions.push_back(JalrInst);
// If .set reorder is active and branch instruction has a delay slot,
// emit a NOP after it.
const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
- if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
- TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst), IDLoc,
- STI);
+ if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
+ createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
+ }
return false;
}
@@ -2630,12 +2150,11 @@ template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
/// @param IsAddress True if the immediate represents an address. False if it
/// is an integer.
/// @param IDLoc Location of the immediate in the source file.
+/// @param Instructions The instructions emitted by this expansion.
bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
unsigned SrcReg, bool Is32BitImm,
- bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
-
+ bool IsAddress, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
if (!Is32BitImm && !isGP64bit()) {
Error(IDLoc, "instruction requires a 64-bit architecture");
return true;
@@ -2661,8 +2180,7 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
UseSrcReg = true;
unsigned TmpReg = DstReg;
- if (UseSrcReg &&
- getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
+ if (UseSrcReg && (DstReg == SrcReg)) {
// At this point we need AT to perform the expansions and we exit if it is
// not available.
unsigned ATReg = getATReg(IDLoc);
@@ -2679,11 +2197,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// traditional assembler behaviour. N32 would normally use addiu for both
// integers and addresses.
if (IsAddress && !Is32BitImm) {
- TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
+ emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
return false;
}
- TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
+ emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
return false;
}
@@ -2695,9 +2213,9 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
return true;
}
- TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
+ emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
if (UseSrcReg)
- TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
+ emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
return false;
}
@@ -2706,33 +2224,34 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
uint16_t Bits15To0 = ImmValue & 0xffff;
+
if (!Is32BitImm && !isInt<32>(ImmValue)) {
// Traditional behaviour seems to special case this particular value. It's
// not clear why other masks are handled differently.
if (ImmValue == 0xffffffff) {
- TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
- TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
+ emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
+ emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
if (UseSrcReg)
- TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
+ emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
return false;
}
// Expand to an ORi instead of a LUi to avoid sign-extending into the
// upper 32 bits.
- TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
- TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
+ emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
+ emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
if (Bits15To0)
- TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
+ emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
if (UseSrcReg)
- TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
+ emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
return false;
}
- TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
+ emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
if (Bits15To0)
- TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
+ emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
if (UseSrcReg)
- TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
+ emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
return false;
}
@@ -2748,11 +2267,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
unsigned LastSet = findLastSet((uint64_t)ImmValue);
unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
- TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
- TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
+ emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
+ emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
if (UseSrcReg)
- TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
+ emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
return false;
}
@@ -2765,7 +2284,7 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
- IDLoc, Out, STI))
+ IDLoc, Instructions))
return false;
// Shift and accumulate into the register. If a 16-bit chunk is zero, then
@@ -2775,8 +2294,9 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
if (ImmChunk != 0) {
- TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
- TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
+ emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
+ Instructions);
+ emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
ShiftCarriedForwards = 0;
}
@@ -2786,23 +2306,24 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// Finish any remaining shifts left by trailing zeros.
if (ShiftCarriedForwards)
- TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
+ emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
+ Instructions);
if (UseSrcReg)
- TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
+ emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
return false;
}
bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
- MCStreamer &Out, const MCSubtargetInfo *STI) {
+ SmallVectorImpl<MCInst> &Instructions) {
const MCOperand &ImmOp = Inst.getOperand(1);
assert(ImmOp.isImm() && "expected immediate operand kind");
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
- Is32BitImm, false, IDLoc, Out, STI))
+ Is32BitImm, false, IDLoc, Instructions))
return true;
return false;
@@ -2811,8 +2332,7 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
const MCOperand &Offset,
bool Is32BitAddress, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
+ SmallVectorImpl<MCInst> &Instructions) {
// la can't produce a usable address when addresses are 64-bit.
if (Is32BitAddress && ABI.ArePtrs64bit()) {
// FIXME: Demote this to a warning and continue as if we had 'dla' instead.
@@ -2821,218 +2341,49 @@ bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
Error(IDLoc, "la used to load 64-bit address");
// Continue as if we had 'dla' instead.
Is32BitAddress = false;
- return true;
}
// dla requires 64-bit addresses.
- if (!Is32BitAddress && !hasMips3()) {
+ if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
Error(IDLoc, "instruction requires a 64-bit architecture");
return true;
}
if (!Offset.isImm())
return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
- Is32BitAddress, IDLoc, Out, STI);
-
- if (!ABI.ArePtrs64bit()) {
- // Continue as if we had 'la' whether we had 'la' or 'dla'.
- Is32BitAddress = true;
- }
+ Is32BitAddress, IDLoc, Instructions);
return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
- IDLoc, Out, STI);
+ IDLoc, Instructions);
}
-bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
- unsigned DstReg, unsigned SrcReg,
- bool Is32BitSym, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- // FIXME: These expansions do not respect -mxgot.
- MipsTargetStreamer &TOut = getTargetStreamer();
- bool UseSrcReg = SrcReg != Mips::NoRegister;
+bool MipsAsmParser::loadAndAddSymbolAddress(
+ const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
+ SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
warnIfNoMacro(IDLoc);
- if (inPicMode() && ABI.IsO32()) {
- MCValue Res;
- if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
- Error(IDLoc, "expected relocatable expression");
- return true;
- }
- if (Res.getSymB() != nullptr) {
- Error(IDLoc, "expected relocatable expression with only one symbol");
- return true;
- }
-
- // The case where the result register is $25 is somewhat special. If the
- // symbol in the final relocation is external and not modified with a
- // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
- if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
- Res.getConstant() == 0 &&
- !(Res.getSymA()->getSymbol().isInSection() ||
- Res.getSymA()->getSymbol().isTemporary() ||
- (Res.getSymA()->getSymbol().isELF() &&
- cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
- ELF::STB_LOCAL))) {
- const MCExpr *CallExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
- TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
- MCOperand::createExpr(CallExpr), IDLoc, STI);
- return false;
- }
-
- // The remaining cases are:
- // External GOT: lw $tmp, %got(symbol+offset)($gp)
- // >addiu $tmp, $tmp, %lo(offset)
- // >addiu $rd, $tmp, $rs
- // Local GOT: lw $tmp, %got(symbol+offset)($gp)
- // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
- // >addiu $rd, $tmp, $rs
- // The addiu's marked with a '>' may be omitted if they are redundant. If
- // this happens then the last instruction must use $rd as the result
- // register.
- const MipsMCExpr *GotExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
- const MCExpr *LoExpr = nullptr;
- if (Res.getSymA()->getSymbol().isInSection() ||
- Res.getSymA()->getSymbol().isTemporary())
- LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
- else if (Res.getConstant() != 0) {
- // External symbols fully resolve the symbol with just the %got(symbol)
- // but we must still account for any offset to the symbol for expressions
- // like symbol+8.
- LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
- }
-
- unsigned TmpReg = DstReg;
- if (UseSrcReg &&
- getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
- SrcReg)) {
- // If $rs is the same as $rd, we need to use AT.
- // If it is not available we exit.
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
- TmpReg = ATReg;
- }
-
- TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
- MCOperand::createExpr(GotExpr), IDLoc, STI);
-
- if (LoExpr)
- TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
- IDLoc, STI);
-
- if (UseSrcReg)
- TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
-
- return false;
- }
-
- if (inPicMode() && ABI.ArePtrs64bit()) {
- MCValue Res;
- if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
- Error(IDLoc, "expected relocatable expression");
- return true;
- }
- if (Res.getSymB() != nullptr) {
- Error(IDLoc, "expected relocatable expression with only one symbol");
- return true;
- }
-
- // The case where the result register is $25 is somewhat special. If the
- // symbol in the final relocation is external and not modified with a
- // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
- if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
- Res.getConstant() == 0 &&
- !(Res.getSymA()->getSymbol().isInSection() ||
- Res.getSymA()->getSymbol().isTemporary() ||
- (Res.getSymA()->getSymbol().isELF() &&
- cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
- ELF::STB_LOCAL))) {
- const MCExpr *CallExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
- TOut.emitRRX(Mips::LD, DstReg, ABI.GetGlobalPtr(),
- MCOperand::createExpr(CallExpr), IDLoc, STI);
- return false;
- }
-
- // The remaining cases are:
- // Small offset: ld $tmp, %got_disp(symbol)($gp)
- // >daddiu $tmp, $tmp, offset
- // >daddu $rd, $tmp, $rs
- // The daddiu's marked with a '>' may be omitted if they are redundant. If
- // this happens then the last instruction must use $rd as the result
- // register.
- const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
- Res.getSymA(),
- getContext());
- const MCExpr *LoExpr = nullptr;
- if (Res.getConstant() != 0) {
- // Symbols fully resolve with just the %got_disp(symbol) but we
- // must still account for any offset to the symbol for
- // expressions like symbol+8.
- LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
-
- // FIXME: Offsets greater than 16 bits are not yet implemented.
- // FIXME: The correct range is a 32-bit sign-extended number.
- if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
- Error(IDLoc, "macro instruction uses large offset, which is not "
- "currently supported");
- return true;
- }
- }
-
- unsigned TmpReg = DstReg;
- if (UseSrcReg &&
- getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
- SrcReg)) {
- // If $rs is the same as $rd, we need to use AT.
- // If it is not available we exit.
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
- TmpReg = ATReg;
- }
-
- TOut.emitRRX(Mips::LD, TmpReg, ABI.GetGlobalPtr(),
- MCOperand::createExpr(GotExpr), IDLoc, STI);
-
- if (LoExpr)
- TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
- IDLoc, STI);
-
- if (UseSrcReg)
- TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
+ const MCExpr *Symbol = cast<MCExpr>(SymExpr);
+ const MipsMCExpr *HiExpr = MipsMCExpr::create(
+ MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
+ const MipsMCExpr *LoExpr = MipsMCExpr::create(
+ MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
- return false;
- }
-
- const MipsMCExpr *HiExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
- const MipsMCExpr *LoExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
+ bool UseSrcReg = SrcReg != Mips::NoRegister;
// This is the 64-bit symbol address expansion.
if (ABI.ArePtrs64bit() && isGP64bit()) {
- // We need AT for the 64-bit expansion in the cases where the optional
- // source register is the destination register and for the superscalar
- // scheduled form.
- //
- // If it is not available we exit if the destination is the same as the
- // source register.
-
- const MipsMCExpr *HighestExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
- const MipsMCExpr *HigherExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
-
- bool RdRegIsRsReg =
- getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
+ // We always need AT for the 64-bit expansion.
+ // If it is not available we exit.
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
- if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
- unsigned ATReg = getATReg(IDLoc);
+ const MipsMCExpr *HighestExpr = MipsMCExpr::create(
+ MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
+ const MipsMCExpr *HigherExpr = MipsMCExpr::create(
+ MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
+ if (UseSrcReg && (DstReg == SrcReg)) {
// If $rs is the same as $rd:
// (d)la $rd, sym($rd) => lui $at, %highest(sym)
// daddiu $at, $at, %higher(sym)
@@ -3041,78 +2392,43 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
// dsll $at, $at, 16
// daddiu $at, $at, %lo(sym)
// daddu $rd, $at, $rd
- TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
- STI);
- TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
- MCOperand::createExpr(HigherExpr), IDLoc, STI);
- TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
- TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
- IDLoc, STI);
- TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
- TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
- IDLoc, STI);
- TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
+ emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
+ Instructions);
+ emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
+ IDLoc, Instructions);
+ emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
+ emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
+ Instructions);
+ emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
+ emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
+ Instructions);
+ emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
return false;
- } else if (canUseATReg() && !RdRegIsRsReg) {
- unsigned ATReg = getATReg(IDLoc);
-
- // If the $rs is different from $rd or if $rs isn't specified and we
- // have $at available:
- // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
- // lui $at, %hi(sym)
- // daddiu $rd, $rd, %higher(sym)
- // daddiu $at, $at, %lo(sym)
- // dsll32 $rd, $rd, 0
- // daddu $rd, $rd, $at
- // (daddu $rd, $rd, $rs)
- //
- // Which is preferred for superscalar issue.
- TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
- STI);
- TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
- TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
- MCOperand::createExpr(HigherExpr), IDLoc, STI);
- TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
- IDLoc, STI);
- TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
- TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
- if (UseSrcReg)
- TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
+ }
- return false;
- } else if (!canUseATReg() && !RdRegIsRsReg) {
- // Otherwise, synthesize the address in the destination register
- // serially:
- // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
- // daddiu $rd, $rd, %higher(sym)
- // dsll $rd, $rd, 16
- // daddiu $rd, $rd, %hi(sym)
- // dsll $rd, $rd, 16
- // daddiu $rd, $rd, %lo(sym)
- TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
- STI);
- TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
- MCOperand::createExpr(HigherExpr), IDLoc, STI);
- TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
- TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
- MCOperand::createExpr(HiExpr), IDLoc, STI);
- TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
- TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
- MCOperand::createExpr(LoExpr), IDLoc, STI);
- if (UseSrcReg)
- TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
+ // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
+ // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
+ // lui $at, %hi(sym)
+ // daddiu $rd, $rd, %higher(sym)
+ // daddiu $at, $at, %lo(sym)
+ // dsll32 $rd, $rd, 0
+ // daddu $rd, $rd, $at
+ // (daddu $rd, $rd, $rs)
+ emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
+ Instructions);
+ emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
+ Instructions);
+ emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
+ IDLoc, Instructions);
+ emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
+ Instructions);
+ emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
+ emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
+ if (UseSrcReg)
+ emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
- return false;
- } else {
- // We have a case where SrcReg == DstReg and we don't have $at
- // available. We can't expand this case, so error out appropriately.
- assert(SrcReg == DstReg && !canUseATReg() &&
- "Could have expanded dla but didn't?");
- reportParseError(IDLoc,
- "pseudo-instruction requires $at, which is not available");
- return true;
- }
+ return false;
}
// And now, the 32-bit symbol address expansion:
@@ -3125,8 +2441,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
// ori $rd, $rd, %lo(sym)
// (addu $rd, $rd, $rs)
unsigned TmpReg = DstReg;
- if (UseSrcReg &&
- getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
+ if (UseSrcReg && (DstReg == SrcReg)) {
// If $rs is the same as $rd, we need to use AT.
// If it is not available we exit.
unsigned ATReg = getATReg(IDLoc);
@@ -3135,320 +2450,20 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
TmpReg = ATReg;
}
- TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
- TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
- IDLoc, STI);
+ emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
+ emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
+ Instructions);
if (UseSrcReg)
- TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
+ emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
else
- assert(
- getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
-
- return false;
-}
-
-// Each double-precision register DO-D15 overlaps with two of the single
-// precision registers F0-F31. As an example, all of the following hold true:
-// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context.
-static unsigned nextReg(unsigned Reg) {
- if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg))
- return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1;
- switch (Reg) {
- default: llvm_unreachable("Unknown register in assembly macro expansion!");
- case Mips::ZERO: return Mips::AT;
- case Mips::AT: return Mips::V0;
- case Mips::V0: return Mips::V1;
- case Mips::V1: return Mips::A0;
- case Mips::A0: return Mips::A1;
- case Mips::A1: return Mips::A2;
- case Mips::A2: return Mips::A3;
- case Mips::A3: return Mips::T0;
- case Mips::T0: return Mips::T1;
- case Mips::T1: return Mips::T2;
- case Mips::T2: return Mips::T3;
- case Mips::T3: return Mips::T4;
- case Mips::T4: return Mips::T5;
- case Mips::T5: return Mips::T6;
- case Mips::T6: return Mips::T7;
- case Mips::T7: return Mips::S0;
- case Mips::S0: return Mips::S1;
- case Mips::S1: return Mips::S2;
- case Mips::S2: return Mips::S3;
- case Mips::S3: return Mips::S4;
- case Mips::S4: return Mips::S5;
- case Mips::S5: return Mips::S6;
- case Mips::S6: return Mips::S7;
- case Mips::S7: return Mips::T8;
- case Mips::T8: return Mips::T9;
- case Mips::T9: return Mips::K0;
- case Mips::K0: return Mips::K1;
- case Mips::K1: return Mips::GP;
- case Mips::GP: return Mips::SP;
- case Mips::SP: return Mips::FP;
- case Mips::FP: return Mips::RA;
- case Mips::RA: return Mips::ZERO;
- case Mips::D0: return Mips::F1;
- case Mips::D1: return Mips::F3;
- case Mips::D2: return Mips::F5;
- case Mips::D3: return Mips::F7;
- case Mips::D4: return Mips::F9;
- case Mips::D5: return Mips::F11;
- case Mips::D6: return Mips::F13;
- case Mips::D7: return Mips::F15;
- case Mips::D8: return Mips::F17;
- case Mips::D9: return Mips::F19;
- case Mips::D10: return Mips::F21;
- case Mips::D11: return Mips::F23;
- case Mips::D12: return Mips::F25;
- case Mips::D13: return Mips::F27;
- case Mips::D14: return Mips::F29;
- case Mips::D15: return Mips::F31;
- }
-}
-
-// FIXME: This method is too general. In principle we should compute the number
-// of instructions required to synthesize the immediate inline compared to
-// synthesizing the address inline and relying on non .text sections.
-// For static O32 and N32 this may yield a small benefit, for static N64 this is
-// likely to yield a much larger benefit as we have to synthesize a 64bit
-// address to load a 64 bit value.
-bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc,
- MCSymbol *Sym) {
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
-
- if(IsPicEnabled) {
- const MCExpr *GotSym =
- MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- const MipsMCExpr *GotExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext());
-
- if(isABI_O32() || isABI_N32()) {
- TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
- IDLoc, STI);
- } else { //isABI_N64()
- TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr),
- IDLoc, STI);
- }
- } else { //!IsPicEnabled
- const MCExpr *HiSym =
- MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- const MipsMCExpr *HiExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext());
-
- // FIXME: This is technically correct but gives a different result to gas,
- // but gas is incomplete there (it has a fixme noting it doesn't work with
- // 64-bit addresses).
- // FIXME: With -msym32 option, the address expansion for N64 should probably
- // use the O32 / N32 case. It's safe to use the 64 address expansion as the
- // symbol's value is considered sign extended.
- if(isABI_O32() || isABI_N32()) {
- TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
- } else { //isABI_N64()
- const MCExpr *HighestSym =
- MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- const MipsMCExpr *HighestExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext());
- const MCExpr *HigherSym =
- MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- const MipsMCExpr *HigherExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext());
-
- TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
- STI);
- TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
- MCOperand::createExpr(HigherExpr), IDLoc, STI);
- TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
- TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
- IDLoc, STI);
- TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
- }
- }
- return false;
-}
-
-bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR,
- bool Is64FPU, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
- assert(Inst.getNumOperands() == 2 && "Invalid operand count");
- assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() &&
- "Invalid instruction operand.");
-
- unsigned FirstReg = Inst.getOperand(0).getReg();
- uint64_t ImmOp64 = Inst.getOperand(1).getImm();
-
- uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
- // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the
- // exponent field), convert it to double (e.g. 1 to 1.0)
- if ((HiImmOp64 & 0x7ff00000) == 0) {
- APFloat RealVal(APFloat::IEEEdouble(), ImmOp64);
- ImmOp64 = RealVal.bitcastToAPInt().getZExtValue();
- }
-
- uint32_t LoImmOp64 = ImmOp64 & 0xffffffff;
- HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32;
-
- if (IsSingle) {
- // Conversion of a double in an uint64_t to a float in a uint32_t,
- // retaining the bit pattern of a float.
- uint32_t ImmOp32;
- double doubleImm = BitsToDouble(ImmOp64);
- float tmp_float = static_cast<float>(doubleImm);
- ImmOp32 = FloatToBits(tmp_float);
-
- if (IsGPR) {
- if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc,
- Out, STI))
- return true;
- return false;
- } else {
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
- if (LoImmOp64 == 0) {
- if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc,
- Out, STI))
- return true;
- TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI);
- return false;
- }
-
- MCSection *CS = getStreamer().getCurrentSectionOnly();
- // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
- // where appropriate.
- MCSection *ReadOnlySection = getContext().getELFSection(
- ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
-
- MCSymbol *Sym = getContext().createTempSymbol();
- const MCExpr *LoSym =
- MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- const MipsMCExpr *LoExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
-
- getStreamer().SwitchSection(ReadOnlySection);
- getStreamer().EmitLabel(Sym, IDLoc);
- getStreamer().EmitIntValue(ImmOp32, 4);
- getStreamer().SwitchSection(CS);
-
- if(emitPartialAddress(TOut, IDLoc, Sym))
- return true;
- TOut.emitRRX(Mips::LWC1, FirstReg, ATReg,
- MCOperand::createExpr(LoExpr), IDLoc, STI);
- }
- return false;
- }
-
- // if(!IsSingle)
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
-
- if (IsGPR) {
- if (LoImmOp64 == 0) {
- if(isABI_N32() || isABI_N64()) {
- if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true,
- IDLoc, Out, STI))
- return true;
- return false;
- } else {
- if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true,
- IDLoc, Out, STI))
- return true;
-
- if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true,
- IDLoc, Out, STI))
- return true;
- return false;
- }
- }
-
- MCSection *CS = getStreamer().getCurrentSectionOnly();
- MCSection *ReadOnlySection = getContext().getELFSection(
- ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
-
- MCSymbol *Sym = getContext().createTempSymbol();
- const MCExpr *LoSym =
- MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- const MipsMCExpr *LoExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
-
- getStreamer().SwitchSection(ReadOnlySection);
- getStreamer().EmitLabel(Sym, IDLoc);
- getStreamer().EmitIntValue(HiImmOp64, 4);
- getStreamer().EmitIntValue(LoImmOp64, 4);
- getStreamer().SwitchSection(CS);
-
- if(emitPartialAddress(TOut, IDLoc, Sym))
- return true;
- if(isABI_N64())
- TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
- MCOperand::createExpr(LoExpr), IDLoc, STI);
- else
- TOut.emitRRX(Mips::ADDiu, ATReg, ATReg,
- MCOperand::createExpr(LoExpr), IDLoc, STI);
-
- if(isABI_N32() || isABI_N64())
- TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI);
- else {
- TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI);
- TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI);
- }
- return false;
- } else { // if(!IsGPR && !IsSingle)
- if ((LoImmOp64 == 0) &&
- !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) {
- // FIXME: In the case where the constant is zero, we can load the
- // register directly from the zero register.
- if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc,
- Out, STI))
- return true;
- if (isABI_N32() || isABI_N64())
- TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI);
- else if (hasMips32r2()) {
- TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
- TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI);
- } else {
- TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI);
- TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI);
- }
- return false;
- }
-
- MCSection *CS = getStreamer().getCurrentSectionOnly();
- // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections
- // where appropriate.
- MCSection *ReadOnlySection = getContext().getELFSection(
- ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
-
- MCSymbol *Sym = getContext().createTempSymbol();
- const MCExpr *LoSym =
- MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
- const MipsMCExpr *LoExpr =
- MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext());
-
- getStreamer().SwitchSection(ReadOnlySection);
- getStreamer().EmitLabel(Sym, IDLoc);
- getStreamer().EmitIntValue(HiImmOp64, 4);
- getStreamer().EmitIntValue(LoImmOp64, 4);
- getStreamer().SwitchSection(CS);
+ assert(DstReg == TmpReg);
- if(emitPartialAddress(TOut, IDLoc, Sym))
- return true;
- TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg,
- MCOperand::createExpr(LoExpr), IDLoc, STI);
- }
return false;
}
-bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
-
+bool MipsAsmParser::expandUncondBranchMMPseudo(
+ MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
"unexpected number of operands");
@@ -3468,9 +2483,9 @@ bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
} else {
if (!isInt<17>(Offset.getImm()))
- return Error(IDLoc, "branch target out of range");
+ Error(IDLoc, "branch target out of range");
if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
- return Error(IDLoc, "branch to misaligned address");
+ Error(IDLoc, "branch to misaligned address");
Inst.clear();
Inst.setOpcode(Mips::BEQ_MM);
Inst.addOperand(MCOperand::createReg(Mips::ZERO));
@@ -3478,20 +2493,19 @@ bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
Inst.addOperand(MCOperand::createImm(Offset.getImm()));
}
}
- Out.EmitInstruction(Inst, *STI);
+ Instructions.push_back(Inst);
// If .set reorder is active and branch instruction has a delay slot,
// emit a NOP after it.
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
- TOut.emitEmptyDelaySlot(true, IDLoc, STI);
+ createNop(true, IDLoc, Instructions);
return false;
}
-bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
+bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
@@ -3499,10 +2513,7 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
assert(ImmOp.isImm() && "expected immediate operand kind");
const MCOperand &MemOffsetOp = Inst.getOperand(2);
- assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
- "expected immediate or expression operand");
-
- bool IsLikely = false;
+ assert(MemOffsetOp.isImm() && "expected immediate operand kind");
unsigned OpCode = 0;
switch(Inst.getOpcode()) {
@@ -3512,29 +2523,16 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
case Mips::BeqImm:
OpCode = Mips::BEQ;
break;
- case Mips::BEQLImmMacro:
- OpCode = Mips::BEQL;
- IsLikely = true;
- break;
- case Mips::BNELImmMacro:
- OpCode = Mips::BNEL;
- IsLikely = true;
- break;
default:
llvm_unreachable("Unknown immediate branch pseudo-instruction.");
break;
}
int64_t ImmValue = ImmOp.getImm();
- if (ImmValue == 0) {
- if (IsLikely) {
- TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO,
- MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
- TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
- } else
- TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
- STI);
- } else {
+ if (ImmValue == 0)
+ emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
+ Instructions);
+ else {
warnIfNoMacro(IDLoc);
unsigned ATReg = getATReg(IDLoc);
@@ -3542,96 +2540,101 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return true;
if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
- IDLoc, Out, STI))
+ IDLoc, Instructions))
return true;
- if (IsLikely) {
- TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg,
- MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI);
- TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
- } else
- TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
+ emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
}
return false;
}
-void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, bool IsLoad) {
- const MCOperand &DstRegOp = Inst.getOperand(0);
- assert(DstRegOp.isReg() && "expected register operand kind");
- const MCOperand &BaseRegOp = Inst.getOperand(1);
- assert(BaseRegOp.isReg() && "expected register operand kind");
- const MCOperand &OffsetOp = Inst.getOperand(2);
-
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned DstReg = DstRegOp.getReg();
- unsigned BaseReg = BaseRegOp.getReg();
- unsigned TmpReg = DstReg;
-
+void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions,
+ bool isLoad, bool isImmOpnd) {
+ unsigned ImmOffset, HiOffset, LoOffset;
+ const MCExpr *ExprOffset;
+ unsigned TmpRegNum;
+ // 1st operand is either the source or destination register.
+ assert(Inst.getOperand(0).isReg() && "expected register operand kind");
+ unsigned RegOpNum = Inst.getOperand(0).getReg();
+ // 2nd operand is the base register.
+ assert(Inst.getOperand(1).isReg() && "expected register operand kind");
+ unsigned BaseRegNum = Inst.getOperand(1).getReg();
+ // 3rd operand is either an immediate or expression.
+ if (isImmOpnd) {
+ assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
+ ImmOffset = Inst.getOperand(2).getImm();
+ LoOffset = ImmOffset & 0x0000ffff;
+ HiOffset = (ImmOffset & 0xffff0000) >> 16;
+ // If msb of LoOffset is 1(negative number) we must increment HiOffset.
+ if (LoOffset & 0x8000)
+ HiOffset++;
+ } else
+ ExprOffset = Inst.getOperand(2).getExpr();
+ // These are some of the types of expansions we perform here:
+ // 1) lw $8, sym => lui $8, %hi(sym)
+ // lw $8, %lo(sym)($8)
+ // 2) lw $8, offset($9) => lui $8, %hi(offset)
+ // add $8, $8, $9
+ // lw $8, %lo(offset)($9)
+ // 3) lw $8, offset($8) => lui $at, %hi(offset)
+ // add $at, $at, $8
+ // lw $8, %lo(offset)($at)
+ // 4) sw $8, sym => lui $at, %hi(sym)
+ // sw $8, %lo(sym)($at)
+ // 5) sw $8, offset($8) => lui $at, %hi(offset)
+ // add $at, $at, $8
+ // sw $8, %lo(offset)($at)
+ // 6) ldc1 $f0, sym => lui $at, %hi(sym)
+ // ldc1 $f0, %lo(sym)($at)
+ //
+ // For load instructions we can use the destination register as a temporary
+ // if base and dst are different (examples 1 and 2) and if the base register
+ // is general purpose otherwise we must use $at (example 6) and error if it's
+ // not available. For stores we must use $at (examples 4 and 5) because we
+ // must not clobber the source register setting up the offset.
const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
- int16_t DstRegClass = Desc.OpInfo[0].RegClass;
- unsigned DstRegClassID =
- getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
- bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
- (DstRegClassID == Mips::GPR64RegClassID);
-
- if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
- // At this point we need AT to perform the expansions
- // and we exit if it is not available.
- TmpReg = getATReg(IDLoc);
- if (!TmpReg)
+ int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
+ unsigned RegClassIDOp0 =
+ getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
+ bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
+ (RegClassIDOp0 == Mips::GPR64RegClassID);
+ if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
+ TmpRegNum = RegOpNum;
+ else {
+ // At this point we need AT to perform the expansions and we exit if it is
+ // not available.
+ TmpRegNum = getATReg(IDLoc);
+ if (!TmpRegNum)
return;
}
- if (OffsetOp.isImm()) {
- int64_t LoOffset = OffsetOp.getImm() & 0xffff;
- int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
-
- // If msb of LoOffset is 1(negative number) we must increment
- // HiOffset to account for the sign-extension of the low part.
- if (LoOffset & 0x8000)
- HiOffset += 0x10000;
-
- bool IsLargeOffset = HiOffset != 0;
-
- if (IsLargeOffset) {
- bool Is32BitImm = (HiOffset >> 32) == 0;
- if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
- IDLoc, Out, STI))
- return;
- }
-
- if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
- TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg,
- BaseReg, IDLoc, STI);
- TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI);
- } else {
- assert(OffsetOp.isExpr() && "expected expression operand kind");
- const MCExpr *ExprOffset = OffsetOp.getExpr();
- MCOperand LoOperand = MCOperand::createExpr(
- MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
- MCOperand HiOperand = MCOperand::createExpr(
- MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
-
- if (IsLoad)
- TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
- LoOperand, TmpReg, IDLoc, STI);
- else
- TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
- LoOperand, TmpReg, IDLoc, STI);
- }
-}
-
-bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
+ emitRX(Mips::LUi, TmpRegNum,
+ isImmOpnd ? MCOperand::createImm(HiOffset)
+ : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
+ IDLoc, Instructions);
+ // Add temp register to base.
+ if (BaseRegNum != Mips::ZERO)
+ emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
+ // And finally, create original instruction with low part
+ // of offset and new base.
+ emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
+ isImmOpnd
+ ? MCOperand::createImm(LoOffset)
+ : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
+ IDLoc, Instructions);
+}
+
+bool
+MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
unsigned OpNum = Inst.getNumOperands();
unsigned Opcode = Inst.getOpcode();
unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
- assert(Inst.getOperand(OpNum - 1).isImm() &&
- Inst.getOperand(OpNum - 2).isReg() &&
- Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
+ assert (Inst.getOperand(OpNum - 1).isImm() &&
+ Inst.getOperand(OpNum - 2).isReg() &&
+ Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
Inst.getOperand(OpNum - 1).getImm() >= 0 &&
@@ -3647,14 +2650,12 @@ bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
}
Inst.setOpcode(NewOpcode);
- Out.EmitInstruction(Inst, *STI);
+ Instructions.push_back(Inst);
return false;
}
bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
+ SmallVectorImpl<MCInst> &Instructions) {
bool EmittedNoMacroWarning = false;
unsigned PseudoOpcode = Inst.getOpcode();
unsigned SrcReg = Inst.getOperand(0).getReg();
@@ -3729,7 +2730,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
}
if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
- false, IDLoc, Out, STI))
+ false, IDLoc, Instructions))
return true;
}
@@ -3740,8 +2741,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
case Mips::BLTUL:
AcceptsEquality = false;
ReverseOrderSLT = false;
- IsUnsigned =
- ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
+ IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
ZeroSrcOpcode = Mips::BGTZ;
ZeroTrgOpcode = Mips::BLTZ;
@@ -3752,8 +2752,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
case Mips::BLEUL:
AcceptsEquality = true;
ReverseOrderSLT = true;
- IsUnsigned =
- ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
+ IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
ZeroSrcOpcode = Mips::BGEZ;
ZeroTrgOpcode = Mips::BLEZ;
@@ -3764,8 +2763,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
case Mips::BGEUL:
AcceptsEquality = true;
ReverseOrderSLT = false;
- IsUnsigned =
- ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
+ IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
ZeroSrcOpcode = Mips::BLEZ;
ZeroTrgOpcode = Mips::BGEZ;
@@ -3776,8 +2774,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
case Mips::BGTUL:
AcceptsEquality = false;
ReverseOrderSLT = true;
- IsUnsigned =
- ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
+ IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
ZeroSrcOpcode = Mips::BLTZ;
ZeroTrgOpcode = Mips::BGTZ;
@@ -3793,37 +2790,37 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// with GAS' behaviour. However, they may not generate the most efficient
// code in some circumstances.
if (PseudoOpcode == Mips::BLT) {
- TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
- IDLoc, STI);
+ emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
+ Instructions);
return false;
}
if (PseudoOpcode == Mips::BLE) {
- TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
- IDLoc, STI);
+ emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
+ Instructions);
Warning(IDLoc, "branch is always taken");
return false;
}
if (PseudoOpcode == Mips::BGE) {
- TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
- IDLoc, STI);
+ emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
+ Instructions);
Warning(IDLoc, "branch is always taken");
return false;
}
if (PseudoOpcode == Mips::BGT) {
- TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
- IDLoc, STI);
+ emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
+ Instructions);
return false;
}
if (PseudoOpcode == Mips::BGTU) {
- TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, STI);
+ emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
return false;
}
if (AcceptsEquality) {
// If both registers are $0 and the pseudo-branch accepts equality, it
// will always be taken, so we emit an unconditional branch.
- TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, STI);
+ emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Warning(IDLoc, "branch is always taken");
return false;
}
@@ -3847,8 +2844,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// the pseudo-branch will always be taken, so we emit an unconditional
// branch.
// This only applies to unsigned pseudo-branches.
- TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, STI);
+ emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Warning(IDLoc, "branch is always taken");
return false;
}
@@ -3865,17 +2862,17 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
//
// Because only BLEU and BGEU branch on equality, we can use the
// AcceptsEquality variable to decide when to emit the BEQZ.
- TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
- IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, STI);
+ emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
+ IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
return false;
}
// If we have a signed pseudo-branch and one of the registers is $0,
// we can use an appropriate compare-to-zero branch. We select which one
// to use in the switch statement above.
- TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
- IsSrcRegZero ? TrgReg : SrcReg,
- MCOperand::createExpr(OffsetExpr), IDLoc, STI);
+ emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
+ IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
+ IDLoc, Instructions);
return false;
}
@@ -3895,7 +2892,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// This is accomplished by using a BNEZ with the result of the SLT.
//
// The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
- // and BLE with BGT), so we change the BNEZ into a BEQZ.
+ // and BLE with BGT), so we change the BNEZ into a a BEQZ.
// Because only BGE and BLE branch on equality, we can use the
// AcceptsEquality variable to decide when to emit the BEQZ.
// Note that the order of the SLT arguments doesn't change between
@@ -3903,155 +2900,102 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
//
// The same applies to the unsigned variants, except that SLTu is used
// instead of SLT.
- TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
- ReverseOrderSLT ? TrgReg : SrcReg,
- ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
-
- TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
- : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
- ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- STI);
+ emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
+ ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
+ IDLoc, Instructions);
+
+ emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
+ : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
+ ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
+ Instructions);
return false;
}
-// Expand a integer division macro.
-//
-// Notably we don't have to emit a warning when encountering $rt as the $zero
-// register, or 0 as an immediate. processInstruction() has already done that.
-//
-// The destination register can only be $zero when expanding (S)DivIMacro or
-// D(S)DivMacro.
-
-bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, const bool IsMips64,
- const bool Signed) {
- MipsTargetStreamer &TOut = getTargetStreamer();
+bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions,
+ const bool IsMips64, const bool Signed) {
+ if (hasMips32r6()) {
+ Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
+ return false;
+ }
warnIfNoMacro(IDLoc);
- const MCOperand &RdRegOp = Inst.getOperand(0);
- assert(RdRegOp.isReg() && "expected register operand kind");
- unsigned RdReg = RdRegOp.getReg();
-
- const MCOperand &RsRegOp = Inst.getOperand(1);
+ const MCOperand &RsRegOp = Inst.getOperand(0);
assert(RsRegOp.isReg() && "expected register operand kind");
unsigned RsReg = RsRegOp.getReg();
- unsigned RtReg;
- int64_t ImmValue;
-
- const MCOperand &RtOp = Inst.getOperand(2);
- assert((RtOp.isReg() || RtOp.isImm()) &&
- "expected register or immediate operand kind");
- if (RtOp.isReg())
- RtReg = RtOp.getReg();
- else
- ImmValue = RtOp.getImm();
-
+ const MCOperand &RtRegOp = Inst.getOperand(1);
+ assert(RtRegOp.isReg() && "expected register operand kind");
+ unsigned RtReg = RtRegOp.getReg();
unsigned DivOp;
unsigned ZeroReg;
- unsigned SubOp;
if (IsMips64) {
DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
ZeroReg = Mips::ZERO_64;
- SubOp = Mips::DSUB;
} else {
DivOp = Signed ? Mips::SDIV : Mips::UDIV;
ZeroReg = Mips::ZERO;
- SubOp = Mips::SUB;
}
bool UseTraps = useTraps();
- unsigned Opcode = Inst.getOpcode();
- bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
- Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
- Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
- Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
-
- bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
- Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
- Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
- Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
-
- if (RtOp.isImm()) {
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
-
- if (ImmValue == 0) {
- if (UseTraps)
- TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
- else
- TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
- return false;
- }
+ if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
+ if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
+ Warning(IDLoc, "dividing zero by zero");
+ if (IsMips64) {
+ if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
+ if (UseTraps) {
+ emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
+ return false;
+ }
- if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
- TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
- return false;
- } else if (isDiv && ImmValue == 1) {
- TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
- return false;
- } else if (isDiv && Signed && ImmValue == -1) {
- TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
- return false;
+ emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
+ return false;
+ }
} else {
- if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
- false, Inst.getLoc(), Out, STI))
- return true;
- TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
- TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
+ emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
return false;
}
- return true;
}
- // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
- // break, insert the trap/break and exit. This gives a different result to
- // GAS. GAS has an inconsistency/missed optimization in that not all cases
- // are handled equivalently. As the observed behaviour is the same, we're ok.
if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
- if (UseTraps) {
- TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
+ Warning(IDLoc, "division by zero");
+ if (Signed) {
+ if (UseTraps) {
+ emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
+ return false;
+ }
+
+ emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
return false;
}
- TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
- return false;
}
- // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
- // not expand to macro sequence.
- if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
- TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
- return false;
- }
-
- // Temporary label for first branch traget
- MCContext &Context = TOut.getStreamer().getContext();
- MCSymbol *BrTarget;
- MCOperand LabelOp;
+ // FIXME: The values for these two BranchTarget variables may be different in
+ // micromips. These magic numbers need to be removed.
+ unsigned BranchTargetNoTraps;
+ unsigned BranchTarget;
if (UseTraps) {
- TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
+ BranchTarget = IsMips64 ? 12 : 8;
+ emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
} else {
+ BranchTarget = IsMips64 ? 20 : 16;
+ BranchTargetNoTraps = 8;
// Branch to the li instruction.
- BrTarget = Context.createTempSymbol();
- LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
- TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI);
+ emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
+ Instructions);
}
- TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
+ emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
if (!UseTraps)
- TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
+ emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
if (!Signed) {
- if (!UseTraps)
- TOut.getStreamer().EmitLabel(BrTarget);
-
- TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
+ emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
return false;
}
@@ -4059,246 +3003,179 @@ bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if (!ATReg)
return true;
- if (!UseTraps)
- TOut.getStreamer().EmitLabel(BrTarget);
-
- TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
-
- // Temporary label for the second branch target.
- MCSymbol *BrTargetEnd = Context.createTempSymbol();
- MCOperand LabelOpEnd =
- MCOperand::createExpr(MCSymbolRefExpr::create(BrTargetEnd, Context));
-
- // Branch to the mflo instruction.
- TOut.emitRRX(Mips::BNE, RtReg, ATReg, LabelOpEnd, IDLoc, STI);
-
+ emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
if (IsMips64) {
- TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
- TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
+ // Branch to the mflo instruction.
+ emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
+ emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
+ emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
} else {
- TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
+ // Branch to the mflo instruction.
+ emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
+ emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
}
if (UseTraps)
- TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
+ emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
else {
// Branch to the mflo instruction.
- TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
- TOut.emitNop(IDLoc, STI);
- TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
+ emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
+ emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
+ emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
}
-
- TOut.getStreamer().EmitLabel(BrTargetEnd);
- TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
- return false;
-}
-
-bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
- SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
-
- assert(Inst.getNumOperands() == 3 && "Invalid operand count");
- assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
- Inst.getOperand(2).isReg() && "Invalid instruction operand.");
-
- unsigned FirstReg = Inst.getOperand(0).getReg();
- unsigned SecondReg = Inst.getOperand(1).getReg();
- unsigned ThirdReg = Inst.getOperand(2).getReg();
-
- if (hasMips1() && !hasMips2()) {
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
- TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
- TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
- TOut.emitNop(IDLoc, STI);
- TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
- TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
- TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
- TOut.emitNop(IDLoc, STI);
- TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
- : Mips::CVT_W_S,
- FirstReg, SecondReg, IDLoc, STI);
- TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
- TOut.emitNop(IDLoc, STI);
- return false;
- }
-
- TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
- : Mips::TRUNC_W_S,
- FirstReg, SecondReg, IDLoc, STI);
-
+ emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
return false;
}
bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
- MCStreamer &Out, const MCSubtargetInfo *STI) {
+ SmallVectorImpl<MCInst> &Instructions) {
if (hasMips32r6() || hasMips64r6()) {
- return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
+ Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
+ return false;
}
+ warnIfNoMacro(IDLoc);
+
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
+
const MCOperand &SrcRegOp = Inst.getOperand(1);
assert(SrcRegOp.isReg() && "expected register operand kind");
+
const MCOperand &OffsetImmOp = Inst.getOperand(2);
assert(OffsetImmOp.isImm() && "expected immediate operand kind");
- MipsTargetStreamer &TOut = getTargetStreamer();
unsigned DstReg = DstRegOp.getReg();
unsigned SrcReg = SrcRegOp.getReg();
int64_t OffsetValue = OffsetImmOp.getImm();
// NOTE: We always need AT for ULHU, as it is always used as the source
// register for one of the LBu's.
- warnIfNoMacro(IDLoc);
unsigned ATReg = getATReg(IDLoc);
if (!ATReg)
return true;
- bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
- if (IsLargeOffset) {
- if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
- IDLoc, Out, STI))
- return true;
- }
-
- int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
- int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
- if (isLittle())
- std::swap(FirstOffset, SecondOffset);
+ // When the value of offset+1 does not fit in 16 bits, we have to load the
+ // offset in AT, (D)ADDu the original source register (if there was one), and
+ // then use AT as the source register for the 2 generated LBu's.
+ bool LoadedOffsetInAT = false;
+ if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
+ LoadedOffsetInAT = true;
- unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
- unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
+ if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
+ true, IDLoc, Instructions))
+ return true;
- unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
- unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
+ // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
+ // because it will make our output more similar to GAS'. For example,
+ // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
+ // instead of just an "ori $1, $9, 32768".
+ // NOTE: If there is no source register specified in the ULHU, the parser
+ // will interpret it as $0.
+ if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
+ createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
+ }
- TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
- FirstOffset, IDLoc, STI);
- TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
- TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
- TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
+ unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
+ unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
+ unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
- return false;
-}
-
-bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- if (hasMips32r6() || hasMips64r6()) {
- return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
+ int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
+ if (isLittle()) {
+ FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
+ SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
+ } else {
+ FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
+ SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
}
- const MCOperand &DstRegOp = Inst.getOperand(0);
- assert(DstRegOp.isReg() && "expected register operand kind");
- const MCOperand &SrcRegOp = Inst.getOperand(1);
- assert(SrcRegOp.isReg() && "expected register operand kind");
- const MCOperand &OffsetImmOp = Inst.getOperand(2);
- assert(OffsetImmOp.isImm() && "expected immediate operand kind");
+ unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned DstReg = DstRegOp.getReg();
- unsigned SrcReg = SrcRegOp.getReg();
- int64_t OffsetValue = OffsetImmOp.getImm();
-
- warnIfNoMacro(IDLoc);
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
+ emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
+ FirstLbuOffset, IDLoc, Instructions);
- bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
- if (IsLargeOffset) {
- if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
- IDLoc, Out, STI))
- return true;
- }
+ emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
+ Instructions);
- int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
- int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
- if (isLittle())
- std::swap(FirstOffset, SecondOffset);
+ emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
- if (IsLargeOffset) {
- TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
- TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
- TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
- TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
- TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
- TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
- } else {
- TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
- TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
- TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
- }
+ emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
return false;
}
-bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
+bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
if (hasMips32r6() || hasMips64r6()) {
- return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
+ Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
+ return false;
}
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
+
const MCOperand &SrcRegOp = Inst.getOperand(1);
assert(SrcRegOp.isReg() && "expected register operand kind");
+
const MCOperand &OffsetImmOp = Inst.getOperand(2);
assert(OffsetImmOp.isImm() && "expected immediate operand kind");
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned DstReg = DstRegOp.getReg();
unsigned SrcReg = SrcRegOp.getReg();
int64_t OffsetValue = OffsetImmOp.getImm();
+ unsigned ATReg = 0;
+
+ // When the value of offset+3 does not fit in 16 bits, we have to load the
+ // offset in AT, (D)ADDu the original source register (if there was one), and
+ // then use AT as the source register for the generated LWL and LWR.
+ bool LoadedOffsetInAT = false;
+ if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
+ ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+ LoadedOffsetInAT = true;
- // Compute left/right load/store offsets.
- bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
- int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
- int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
- if (isLittle())
- std::swap(LxlOffset, LxrOffset);
-
- bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
- bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
- unsigned TmpReg = SrcReg;
- if (IsLargeOffset || DoMove) {
warnIfNoMacro(IDLoc);
- TmpReg = getATReg(IDLoc);
- if (!TmpReg)
- return true;
- }
- if (IsLargeOffset) {
- if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
- IDLoc, Out, STI))
+ if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
+ true, IDLoc, Instructions))
return true;
- }
- if (DoMove)
- std::swap(DstReg, TmpReg);
+ // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
+ // because it will make our output more similar to GAS'. For example,
+ // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
+ // instead of just an "ori $1, $9, 32768".
+ // NOTE: If there is no source register specified in the ULW, the parser
+ // will interpret it as $0.
+ if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
+ createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
+ }
+
+ unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
+ int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
+ if (isLittle()) {
+ LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
+ RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
+ } else {
+ LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
+ RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
+ }
- unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
- unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
- TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
- TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
+ emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
+ Instructions);
- if (DoMove)
- TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
+ emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
+ Instructions);
return false;
}
bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
+ SmallVectorImpl<MCInst> &Instructions) {
- assert(Inst.getNumOperands() == 3 && "Invalid operand count");
- assert(Inst.getOperand(0).isReg() &&
- Inst.getOperand(1).isReg() &&
- Inst.getOperand(2).isImm() && "Invalid instruction operand.");
+ assert (Inst.getNumOperands() == 3 && "Invalid operand count");
+ assert (Inst.getOperand(0).isReg() &&
+ Inst.getOperand(1).isReg() &&
+ Inst.getOperand(2).isImm() && "Invalid instruction operand.");
unsigned ATReg = Mips::NoRegister;
unsigned FinalDstReg = Mips::NoRegister;
@@ -4306,7 +3183,7 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
unsigned SrcReg = Inst.getOperand(1).getReg();
int64_t ImmValue = Inst.getOperand(2).getImm();
- bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue));
+ bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
unsigned FinalOpcode = Inst.getOpcode();
@@ -4318,88 +3195,48 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
DstReg = ATReg;
}
- if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false,
- Inst.getLoc(), Out, STI)) {
+ if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
switch (FinalOpcode) {
default:
llvm_unreachable("unimplemented expansion");
- case Mips::ADDi:
+ case (Mips::ADDi):
FinalOpcode = Mips::ADD;
break;
- case Mips::ADDiu:
+ case (Mips::ADDiu):
FinalOpcode = Mips::ADDu;
break;
- case Mips::ANDi:
+ case (Mips::ANDi):
FinalOpcode = Mips::AND;
break;
- case Mips::NORImm:
+ case (Mips::NORImm):
FinalOpcode = Mips::NOR;
break;
- case Mips::ORi:
+ case (Mips::ORi):
FinalOpcode = Mips::OR;
break;
- case Mips::SLTi:
+ case (Mips::SLTi):
FinalOpcode = Mips::SLT;
break;
- case Mips::SLTiu:
+ case (Mips::SLTiu):
FinalOpcode = Mips::SLTu;
break;
- case Mips::XORi:
+ case (Mips::XORi):
FinalOpcode = Mips::XOR;
break;
- case Mips::ADDi_MM:
- FinalOpcode = Mips::ADD_MM;
- break;
- case Mips::ADDiu_MM:
- FinalOpcode = Mips::ADDu_MM;
- break;
- case Mips::ANDi_MM:
- FinalOpcode = Mips::AND_MM;
- break;
- case Mips::ORi_MM:
- FinalOpcode = Mips::OR_MM;
- break;
- case Mips::SLTi_MM:
- FinalOpcode = Mips::SLT_MM;
- break;
- case Mips::SLTiu_MM:
- FinalOpcode = Mips::SLTu_MM;
- break;
- case Mips::XORi_MM:
- FinalOpcode = Mips::XOR_MM;
- break;
- case Mips::ANDi64:
- FinalOpcode = Mips::AND64;
- break;
- case Mips::NORImm64:
- FinalOpcode = Mips::NOR64;
- break;
- case Mips::ORi64:
- FinalOpcode = Mips::OR64;
- break;
- case Mips::SLTImm64:
- FinalOpcode = Mips::SLT64;
- break;
- case Mips::SLTUImm64:
- FinalOpcode = Mips::SLTu64;
- break;
- case Mips::XORi64:
- FinalOpcode = Mips::XOR64;
- break;
}
if (FinalDstReg == Mips::NoRegister)
- TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
+ emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
else
- TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
+ emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
+ Instructions);
return false;
}
return true;
}
-bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
+bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -4410,6 +3247,7 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
unsigned SecondShift = Mips::NOP;
if (hasMips32r2()) {
+
if (DReg == SReg) {
TmpReg = getATReg(Inst.getLoc());
if (!TmpReg)
@@ -4417,13 +3255,13 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
if (Inst.getOpcode() == Mips::ROL) {
- TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
- TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
+ emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
+ emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
return false;
}
if (Inst.getOpcode() == Mips::ROR) {
- TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
+ emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
return false;
}
@@ -4431,6 +3269,7 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
if (hasMips32()) {
+
switch (Inst.getOpcode()) {
default:
llvm_unreachable("unexpected instruction opcode");
@@ -4448,10 +3287,10 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if (!ATReg)
return true;
- TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
- TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
- TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
- TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
+ emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
+ emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
+ emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
+ emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
return false;
}
@@ -4460,9 +3299,8 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
+ SmallVectorImpl<MCInst> &Instructions) {
+
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -4472,17 +3310,18 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
unsigned SecondShift = Mips::NOP;
if (hasMips32r2()) {
+
if (Inst.getOpcode() == Mips::ROLImm) {
uint64_t MaxShift = 32;
uint64_t ShiftValue = ImmValue;
if (ImmValue != 0)
ShiftValue = MaxShift - ImmValue;
- TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
+ emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
return false;
}
if (Inst.getOpcode() == Mips::RORImm) {
- TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
+ emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
return false;
}
@@ -4490,8 +3329,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
}
if (hasMips32()) {
+
if (ImmValue == 0) {
- TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
+ emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
return false;
}
@@ -4512,9 +3352,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
- TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
- TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
+ emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
+ emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
+ emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
return false;
}
@@ -4522,9 +3362,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
return true;
}
-bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
+bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -4535,6 +3375,7 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
unsigned SecondShift = Mips::NOP;
if (hasMips64r2()) {
+
if (TmpReg == SReg) {
TmpReg = getATReg(Inst.getLoc());
if (!TmpReg)
@@ -4542,13 +3383,13 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
if (Inst.getOpcode() == Mips::DROL) {
- TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
- TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
+ emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
+ emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
return false;
}
if (Inst.getOpcode() == Mips::DROR) {
- TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
+ emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
return false;
}
@@ -4556,6 +3397,7 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
if (hasMips64()) {
+
switch (Inst.getOpcode()) {
default:
llvm_unreachable("unexpected instruction opcode");
@@ -4573,10 +3415,10 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if (!ATReg)
return true;
- TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
- TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
- TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
- TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
+ emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
+ emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
+ emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
+ emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
return false;
}
@@ -4585,9 +3427,8 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
+ SmallVectorImpl<MCInst> &Instructions) {
+
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -4599,6 +3440,7 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
MCInst TmpInst;
if (hasMips64r2()) {
+
unsigned FinalOpcode = Mips::NOP;
if (ImmValue == 0)
FinalOpcode = Mips::DROTR;
@@ -4620,14 +3462,15 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
if (Inst.getOpcode() == Mips::DROLImm)
ShiftValue = (32 - ImmValue % 32) % 32;
- TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
+ emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
return false;
}
if (hasMips64()) {
+
if (ImmValue == 0) {
- TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
+ emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
return false;
}
@@ -4668,10 +3511,9 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
- TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
- Inst.getLoc(), STI);
- TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
+ emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
+ emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
+ emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
return false;
}
@@ -4679,620 +3521,49 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
return true;
}
-bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned FirstRegOp = Inst.getOperand(0).getReg();
- unsigned SecondRegOp = Inst.getOperand(1).getReg();
-
- TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
- if (FirstRegOp != SecondRegOp)
- TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
+void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ if (hasShortDelaySlot)
+ emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
else
- TOut.emitEmptyDelaySlot(false, IDLoc, STI);
- TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
-
- return false;
+ emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
}
-bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned ATReg = Mips::NoRegister;
- unsigned DstReg = Inst.getOperand(0).getReg();
- unsigned SrcReg = Inst.getOperand(1).getReg();
- int32_t ImmValue = Inst.getOperand(2).getImm();
-
- ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
-
- loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out,
- STI);
-
- TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT,
- SrcReg, ATReg, IDLoc, STI);
-
- TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
-
- return false;
-}
-
-bool MipsAsmParser::expandMulO(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned ATReg = Mips::NoRegister;
- unsigned DstReg = Inst.getOperand(0).getReg();
- unsigned SrcReg = Inst.getOperand(1).getReg();
- unsigned TmpReg = Inst.getOperand(2).getReg();
-
- ATReg = getATReg(Inst.getLoc());
- if (!ATReg)
- return true;
-
- TOut.emitRR(Inst.getOpcode() == Mips::MULOMacro ? Mips::MULT : Mips::DMULT,
- SrcReg, TmpReg, IDLoc, STI);
-
- TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
-
- TOut.emitRRI(Inst.getOpcode() == Mips::MULOMacro ? Mips::SRA : Mips::DSRA32,
- DstReg, DstReg, 0x1F, IDLoc, STI);
-
- TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
-
- if (useTraps()) {
- TOut.emitRRI(Mips::TNE, DstReg, ATReg, 6, IDLoc, STI);
- } else {
- MCContext & Context = TOut.getStreamer().getContext();
- MCSymbol * BrTarget = Context.createTempSymbol();
- MCOperand LabelOp =
- MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
-
- TOut.emitRRX(Mips::BEQ, DstReg, ATReg, LabelOp, IDLoc, STI);
- if (AssemblerOptions.back()->isReorder())
- TOut.emitNop(IDLoc, STI);
- TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
-
- TOut.getStreamer().EmitLabel(BrTarget);
- }
- TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
-
- return false;
+void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
+ unsigned TrgReg, bool Is64Bit,
+ SmallVectorImpl<MCInst> &Instructions) {
+ emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
+ Instructions);
}
-bool MipsAsmParser::expandMulOU(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned ATReg = Mips::NoRegister;
- unsigned DstReg = Inst.getOperand(0).getReg();
- unsigned SrcReg = Inst.getOperand(1).getReg();
- unsigned TmpReg = Inst.getOperand(2).getReg();
-
- ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
-
- TOut.emitRR(Inst.getOpcode() == Mips::MULOUMacro ? Mips::MULTu : Mips::DMULTu,
- SrcReg, TmpReg, IDLoc, STI);
-
- TOut.emitR(Mips::MFHI, ATReg, IDLoc, STI);
- TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
- if (useTraps()) {
- TOut.emitRRI(Mips::TNE, ATReg, Mips::ZERO, 6, IDLoc, STI);
- } else {
- MCContext & Context = TOut.getStreamer().getContext();
- MCSymbol * BrTarget = Context.createTempSymbol();
- MCOperand LabelOp =
- MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context));
-
- TOut.emitRRX(Mips::BEQ, ATReg, Mips::ZERO, LabelOp, IDLoc, STI);
- if (AssemblerOptions.back()->isReorder())
- TOut.emitNop(IDLoc, STI);
- TOut.emitII(Mips::BREAK, 6, 0, IDLoc, STI);
-
- TOut.getStreamer().EmitLabel(BrTarget);
+void MipsAsmParser::createCpRestoreMemOp(
+ bool IsLoad, int StackOffset, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ // If the offset can not fit into 16 bits, we need to expand.
+ if (!isInt<16>(StackOffset)) {
+ MCInst MemInst;
+ MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
+ MemInst.addOperand(MCOperand::createReg(Mips::GP));
+ MemInst.addOperand(MCOperand::createReg(Mips::SP));
+ MemInst.addOperand(MCOperand::createImm(StackOffset));
+ expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
+ return;
}
- return false;
-}
-
-bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned DstReg = Inst.getOperand(0).getReg();
- unsigned SrcReg = Inst.getOperand(1).getReg();
- unsigned TmpReg = Inst.getOperand(2).getReg();
-
- TOut.emitRR(Mips::DMULTu, SrcReg, TmpReg, IDLoc, STI);
- TOut.emitR(Mips::MFLO, DstReg, IDLoc, STI);
-
- return false;
-}
-
-// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
-// lw $<reg+1>>, offset+4($reg2)'
-// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
-// sw $<reg+1>>, offset+4($reg2)'
-// for O32.
-bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out,
- const MCSubtargetInfo *STI,
- bool IsLoad) {
- if (!isABI_O32())
- return true;
-
- warnIfNoMacro(IDLoc);
-
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
- unsigned FirstReg = Inst.getOperand(0).getReg();
- unsigned SecondReg = nextReg(FirstReg);
- unsigned BaseReg = Inst.getOperand(1).getReg();
- if (!SecondReg)
- return true;
-
- warnIfRegIndexIsAT(FirstReg, IDLoc);
-
- assert(Inst.getOperand(2).isImm() &&
- "Offset for load macro is not immediate!");
-
- MCOperand &FirstOffset = Inst.getOperand(2);
- signed NextOffset = FirstOffset.getImm() + 4;
- MCOperand SecondOffset = MCOperand::createImm(NextOffset);
-
- if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
- return true;
-
- // For loads, clobber the base register with the second load instead of the
- // first if the BaseReg == FirstReg.
- if (FirstReg != BaseReg || !IsLoad) {
- TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
- TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
- } else {
- TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
- TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
- }
-
- return false;
-}
-
-bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
-
- warnIfNoMacro(IDLoc);
- MipsTargetStreamer &TOut = getTargetStreamer();
-
- if (Inst.getOperand(1).getReg() != Mips::ZERO &&
- Inst.getOperand(2).getReg() != Mips::ZERO) {
- TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
- Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
- IDLoc, STI);
- TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
- Inst.getOperand(0).getReg(), 1, IDLoc, STI);
- return false;
- }
-
- unsigned Reg = 0;
- if (Inst.getOperand(1).getReg() == Mips::ZERO) {
- Reg = Inst.getOperand(2).getReg();
- } else {
- Reg = Inst.getOperand(1).getReg();
- }
- TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
- return false;
-}
-
-bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- warnIfNoMacro(IDLoc);
- MipsTargetStreamer &TOut = getTargetStreamer();
-
- unsigned Opc;
- int64_t Imm = Inst.getOperand(2).getImm();
- unsigned Reg = Inst.getOperand(1).getReg();
-
- if (Imm == 0) {
- TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
- Inst.getOperand(1).getReg(), 1, IDLoc, STI);
- return false;
- } else {
-
- if (Reg == Mips::ZERO) {
- Warning(IDLoc, "comparison is always false");
- TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
- Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
- return false;
- }
-
- if (Imm > -0x8000 && Imm < 0) {
- Imm = -Imm;
- Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
- } else {
- Opc = Mips::XORi;
- }
- }
- if (!isUInt<16>(Imm)) {
- unsigned ATReg = getATReg(IDLoc);
- if (!ATReg)
- return true;
-
- if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
- Out, STI))
- return true;
-
- TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
- Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
- TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
- Inst.getOperand(0).getReg(), 1, IDLoc, STI);
- return false;
- }
-
- TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
- Imm, IDLoc, STI);
- TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
- Inst.getOperand(0).getReg(), 1, IDLoc, STI);
- return false;
-}
-
-// Map the DSP accumulator and control register to the corresponding gpr
-// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
-// do not map the DSP registers contigously to gpr registers.
-static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
- switch (Inst.getOpcode()) {
- case Mips::MFTLO:
- case Mips::MTTLO:
- switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
- case Mips::AC0:
- return Mips::ZERO;
- case Mips::AC1:
- return Mips::A0;
- case Mips::AC2:
- return Mips::T0;
- case Mips::AC3:
- return Mips::T4;
- default:
- llvm_unreachable("Unknown register for 'mttr' alias!");
- }
- case Mips::MFTHI:
- case Mips::MTTHI:
- switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
- case Mips::AC0:
- return Mips::AT;
- case Mips::AC1:
- return Mips::A1;
- case Mips::AC2:
- return Mips::T1;
- case Mips::AC3:
- return Mips::T5;
- default:
- llvm_unreachable("Unknown register for 'mttr' alias!");
- }
- case Mips::MFTACX:
- case Mips::MTTACX:
- switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
- case Mips::AC0:
- return Mips::V0;
- case Mips::AC1:
- return Mips::A2;
- case Mips::AC2:
- return Mips::T2;
- case Mips::AC3:
- return Mips::T6;
- default:
- llvm_unreachable("Unknown register for 'mttr' alias!");
- }
- case Mips::MFTDSP:
- case Mips::MTTDSP:
- return Mips::S0;
- default:
- llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
- }
-}
-
-// Map the floating point register operand to the corresponding register
-// operand.
-static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
- switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
- case Mips::F0: return Mips::ZERO;
- case Mips::F1: return Mips::AT;
- case Mips::F2: return Mips::V0;
- case Mips::F3: return Mips::V1;
- case Mips::F4: return Mips::A0;
- case Mips::F5: return Mips::A1;
- case Mips::F6: return Mips::A2;
- case Mips::F7: return Mips::A3;
- case Mips::F8: return Mips::T0;
- case Mips::F9: return Mips::T1;
- case Mips::F10: return Mips::T2;
- case Mips::F11: return Mips::T3;
- case Mips::F12: return Mips::T4;
- case Mips::F13: return Mips::T5;
- case Mips::F14: return Mips::T6;
- case Mips::F15: return Mips::T7;
- case Mips::F16: return Mips::S0;
- case Mips::F17: return Mips::S1;
- case Mips::F18: return Mips::S2;
- case Mips::F19: return Mips::S3;
- case Mips::F20: return Mips::S4;
- case Mips::F21: return Mips::S5;
- case Mips::F22: return Mips::S6;
- case Mips::F23: return Mips::S7;
- case Mips::F24: return Mips::T8;
- case Mips::F25: return Mips::T9;
- case Mips::F26: return Mips::K0;
- case Mips::F27: return Mips::K1;
- case Mips::F28: return Mips::GP;
- case Mips::F29: return Mips::SP;
- case Mips::F30: return Mips::FP;
- case Mips::F31: return Mips::RA;
- default: llvm_unreachable("Unknown register for mttc1 alias!");
- }
-}
-
-// Map the coprocessor operand the corresponding gpr register operand.
-static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
- switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
- case Mips::COP00: return Mips::ZERO;
- case Mips::COP01: return Mips::AT;
- case Mips::COP02: return Mips::V0;
- case Mips::COP03: return Mips::V1;
- case Mips::COP04: return Mips::A0;
- case Mips::COP05: return Mips::A1;
- case Mips::COP06: return Mips::A2;
- case Mips::COP07: return Mips::A3;
- case Mips::COP08: return Mips::T0;
- case Mips::COP09: return Mips::T1;
- case Mips::COP010: return Mips::T2;
- case Mips::COP011: return Mips::T3;
- case Mips::COP012: return Mips::T4;
- case Mips::COP013: return Mips::T5;
- case Mips::COP014: return Mips::T6;
- case Mips::COP015: return Mips::T7;
- case Mips::COP016: return Mips::S0;
- case Mips::COP017: return Mips::S1;
- case Mips::COP018: return Mips::S2;
- case Mips::COP019: return Mips::S3;
- case Mips::COP020: return Mips::S4;
- case Mips::COP021: return Mips::S5;
- case Mips::COP022: return Mips::S6;
- case Mips::COP023: return Mips::S7;
- case Mips::COP024: return Mips::T8;
- case Mips::COP025: return Mips::T9;
- case Mips::COP026: return Mips::K0;
- case Mips::COP027: return Mips::K1;
- case Mips::COP028: return Mips::GP;
- case Mips::COP029: return Mips::SP;
- case Mips::COP030: return Mips::FP;
- case Mips::COP031: return Mips::RA;
- default: llvm_unreachable("Unknown register for mttc0 alias!");
- }
-}
-
-/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
-/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
-bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer &TOut = getTargetStreamer();
- unsigned rd = 0;
- unsigned u = 1;
- unsigned sel = 0;
- unsigned h = 0;
- bool IsMFTR = false;
- switch (Inst.getOpcode()) {
- case Mips::MFTC0:
- IsMFTR = true;
- LLVM_FALLTHROUGH;
- case Mips::MTTC0:
- u = 0;
- rd = getRegisterForMxtrC0(Inst, IsMFTR);
- sel = Inst.getOperand(2).getImm();
- break;
- case Mips::MFTGPR:
- IsMFTR = true;
- LLVM_FALLTHROUGH;
- case Mips::MTTGPR:
- rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
- break;
- case Mips::MFTLO:
- case Mips::MFTHI:
- case Mips::MFTACX:
- case Mips::MFTDSP:
- IsMFTR = true;
- LLVM_FALLTHROUGH;
- case Mips::MTTLO:
- case Mips::MTTHI:
- case Mips::MTTACX:
- case Mips::MTTDSP:
- rd = getRegisterForMxtrDSP(Inst, IsMFTR);
- sel = 1;
- break;
- case Mips::MFTHC1:
- h = 1;
- LLVM_FALLTHROUGH;
- case Mips::MFTC1:
- IsMFTR = true;
- rd = getRegisterForMxtrFP(Inst, IsMFTR);
- sel = 2;
- break;
- case Mips::MTTHC1:
- h = 1;
- LLVM_FALLTHROUGH;
- case Mips::MTTC1:
- rd = getRegisterForMxtrFP(Inst, IsMFTR);
- sel = 2;
- break;
- case Mips::CFTC1:
- IsMFTR = true;
- LLVM_FALLTHROUGH;
- case Mips::CTTC1:
- rd = getRegisterForMxtrFP(Inst, IsMFTR);
- sel = 3;
- break;
- }
- unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
- unsigned Op1 =
- IsMFTR ? rd
- : (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
- : Inst.getOperand(0).getReg());
-
- TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
- STI);
- return false;
-}
-
-unsigned
-MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
- const OperandVector &Operands) {
- switch (Inst.getOpcode()) {
- default:
- return Match_Success;
- case Mips::DATI:
- case Mips::DAHI:
- if (static_cast<MipsOperand &>(*Operands[1])
- .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
- return Match_Success;
- return Match_RequiresSameSrcAndDst;
- }
+ emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
+ Instructions);
}
unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
- switch (Inst.getOpcode()) {
- // As described by the MIPSR6 spec, daui must not use the zero operand for
- // its source operand.
- case Mips::DAUI:
- if (Inst.getOperand(1).getReg() == Mips::ZERO ||
- Inst.getOperand(1).getReg() == Mips::ZERO_64)
- return Match_RequiresNoZeroRegister;
- return Match_Success;
// As described by the Mips32r2 spec, the registers Rd and Rs for
// jalr.hb must be different.
- // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
- // and registers Rd and Base for microMIPS lwp instruction
- case Mips::JALR_HB:
- case Mips::JALR_HB64:
- case Mips::JALRC_HB_MMR6:
- case Mips::JALRC_MMR6:
- if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
- return Match_RequiresDifferentSrcAndDst;
- return Match_Success;
- case Mips::LWP_MM:
- if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
- return Match_RequiresDifferentSrcAndDst;
- return Match_Success;
- case Mips::SYNC:
- if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
- return Match_NonZeroOperandForSync;
- return Match_Success;
- case Mips::MFC0:
- case Mips::MTC0:
- case Mips::MTC2:
- case Mips::MFC2:
- if (Inst.getOperand(2).getImm() != 0 && !hasMips32())
- return Match_NonZeroOperandForMTCX;
- return Match_Success;
- // As described the MIPSR6 spec, the compact branches that compare registers
- // must:
- // a) Not use the zero register.
- // b) Not use the same register twice.
- // c) rs < rt for bnec, beqc.
- // NB: For this case, the encoding will swap the operands as their
- // ordering doesn't matter. GAS performs this transformation too.
- // Hence, that constraint does not have to be enforced.
- //
- // The compact branches that branch iff the signed addition of two registers
- // would overflow must have rs >= rt. That can be handled like beqc/bnec with
- // operand swapping. They do not have restriction of using the zero register.
- case Mips::BLEZC: case Mips::BLEZC_MMR6:
- case Mips::BGEZC: case Mips::BGEZC_MMR6:
- case Mips::BGTZC: case Mips::BGTZC_MMR6:
- case Mips::BLTZC: case Mips::BLTZC_MMR6:
- case Mips::BEQZC: case Mips::BEQZC_MMR6:
- case Mips::BNEZC: case Mips::BNEZC_MMR6:
- case Mips::BLEZC64:
- case Mips::BGEZC64:
- case Mips::BGTZC64:
- case Mips::BLTZC64:
- case Mips::BEQZC64:
- case Mips::BNEZC64:
- if (Inst.getOperand(0).getReg() == Mips::ZERO ||
- Inst.getOperand(0).getReg() == Mips::ZERO_64)
- return Match_RequiresNoZeroRegister;
- return Match_Success;
- case Mips::BGEC: case Mips::BGEC_MMR6:
- case Mips::BLTC: case Mips::BLTC_MMR6:
- case Mips::BGEUC: case Mips::BGEUC_MMR6:
- case Mips::BLTUC: case Mips::BLTUC_MMR6:
- case Mips::BEQC: case Mips::BEQC_MMR6:
- case Mips::BNEC: case Mips::BNEC_MMR6:
- case Mips::BGEC64:
- case Mips::BLTC64:
- case Mips::BGEUC64:
- case Mips::BLTUC64:
- case Mips::BEQC64:
- case Mips::BNEC64:
- if (Inst.getOperand(0).getReg() == Mips::ZERO ||
- Inst.getOperand(0).getReg() == Mips::ZERO_64)
- return Match_RequiresNoZeroRegister;
- if (Inst.getOperand(1).getReg() == Mips::ZERO ||
- Inst.getOperand(1).getReg() == Mips::ZERO_64)
- return Match_RequiresNoZeroRegister;
- if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
- return Match_RequiresDifferentOperands;
- return Match_Success;
- case Mips::DINS: {
- assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
- "Operands must be immediates for dins!");
- const signed Pos = Inst.getOperand(2).getImm();
- const signed Size = Inst.getOperand(3).getImm();
- if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
- return Match_RequiresPosSizeRange0_32;
- return Match_Success;
- }
- case Mips::DINSM:
- case Mips::DINSU: {
- assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
- "Operands must be immediates for dinsm/dinsu!");
- const signed Pos = Inst.getOperand(2).getImm();
- const signed Size = Inst.getOperand(3).getImm();
- if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
- return Match_RequiresPosSizeRange33_64;
- return Match_Success;
- }
- case Mips::DEXT: {
- assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
- "Operands must be immediates for DEXTM!");
- const signed Pos = Inst.getOperand(2).getImm();
- const signed Size = Inst.getOperand(3).getImm();
- if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
- return Match_RequiresPosSizeUImm6;
- return Match_Success;
- }
- case Mips::DEXTM:
- case Mips::DEXTU: {
- assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
- "Operands must be immediates for dextm/dextu!");
- const signed Pos = Inst.getOperand(2).getImm();
- const signed Size = Inst.getOperand(3).getImm();
- if ((32 > (Pos + Size)) || ((Pos + Size) > 64))
- return Match_RequiresPosSizeRange33_64;
- return Match_Success;
- }
- case Mips::CRC32B: case Mips::CRC32CB:
- case Mips::CRC32H: case Mips::CRC32CH:
- case Mips::CRC32W: case Mips::CRC32CW:
- case Mips::CRC32D: case Mips::CRC32CD:
- if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg())
- return Match_RequiresSameSrcAndDst;
- return Match_Success;
- }
-
- uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
- if ((TSFlags & MipsII::HasFCCRegOperand) &&
- (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
- return Match_NoFCCRegisterForCurrentISA;
+ unsigned Opcode = Inst.getOpcode();
- return Match_Success;
+ if (Opcode == Mips::JALR_HB &&
+ (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
+ return Match_RequiresDifferentSrcAndDst;
+ return Match_Success;
}
static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
@@ -5311,15 +3582,20 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
MCStreamer &Out,
uint64_t &ErrorInfo,
bool MatchingInlineAsm) {
+
MCInst Inst;
+ SmallVector<MCInst, 8> Instructions;
unsigned MatchResult =
MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
switch (MatchResult) {
- case Match_Success:
- if (processInstruction(Inst, IDLoc, Out, STI))
+ case Match_Success: {
+ if (processInstruction(Inst, IDLoc, Instructions))
return true;
+ for (unsigned i = 0; i < Instructions.size(); i++)
+ Out.EmitInstruction(Instructions[i], getSTI());
return false;
+ }
case Match_MissingFeature:
Error(IDLoc, "instruction requires a CPU feature not currently enabled");
return true;
@@ -5336,24 +3612,10 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(ErrorLoc, "invalid operand for instruction");
}
- case Match_NonZeroOperandForSync:
- return Error(IDLoc,
- "s-type must be zero or unspecified for pre-MIPS32 ISAs");
- case Match_NonZeroOperandForMTCX:
- return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs");
case Match_MnemonicFail:
return Error(IDLoc, "invalid instruction");
case Match_RequiresDifferentSrcAndDst:
return Error(IDLoc, "source and destination must be different");
- case Match_RequiresDifferentOperands:
- return Error(IDLoc, "registers must be different");
- case Match_RequiresNoZeroRegister:
- return Error(IDLoc, "invalid operand ($zero) for instruction");
- case Match_RequiresSameSrcAndDst:
- return Error(IDLoc, "source and destination must match");
- case Match_NoFCCRegisterForCurrentISA:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "non-zero fcc register doesn't exist in current ISA level");
case Match_Immz:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
case Match_UImm1_0:
@@ -5371,15 +3633,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_UImm4_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 4-bit unsigned immediate");
- case Match_SImm4_0:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 4-bit signed immediate");
case Match_UImm5_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 5-bit unsigned immediate");
- case Match_SImm5_0:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 5-bit signed immediate");
case Match_UImm5_1:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range 1 .. 32");
@@ -5397,109 +3653,21 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_UImm5_Lsl2:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected both 7-bit unsigned immediate and multiple of 4");
- case Match_UImmRange2_64:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected immediate in range 2 .. 64");
case Match_UImm6_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 6-bit unsigned immediate");
- case Match_UImm6_Lsl2:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected both 8-bit unsigned immediate and multiple of 4");
- case Match_SImm6_0:
+ case Match_SImm6:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 6-bit signed immediate");
case Match_UImm7_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 7-bit unsigned immediate");
- case Match_UImm7_N1:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected immediate in range -1 .. 126");
- case Match_SImm7_Lsl2:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected both 9-bit signed immediate and multiple of 4");
case Match_UImm8_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 8-bit unsigned immediate");
case Match_UImm10_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 10-bit unsigned immediate");
- case Match_SImm10_0:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 10-bit signed immediate");
- case Match_SImm11_0:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 11-bit signed immediate");
- case Match_UImm16:
- case Match_UImm16_Relaxed:
- case Match_UImm16_AltRelaxed:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 16-bit unsigned immediate");
- case Match_SImm16:
- case Match_SImm16_Relaxed:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 16-bit signed immediate");
- case Match_SImm19_Lsl2:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected both 19-bit signed immediate and multiple of 4");
- case Match_UImm20_0:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 20-bit unsigned immediate");
- case Match_UImm26_0:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 26-bit unsigned immediate");
- case Match_SImm32:
- case Match_SImm32_Relaxed:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 32-bit signed immediate");
- case Match_UImm32_Coerced:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected 32-bit immediate");
- case Match_MemSImm9:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected memory with 9-bit signed offset");
- case Match_MemSImm10:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected memory with 10-bit signed offset");
- case Match_MemSImm10Lsl1:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected memory with 11-bit signed offset and multiple of 2");
- case Match_MemSImm10Lsl2:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected memory with 12-bit signed offset and multiple of 4");
- case Match_MemSImm10Lsl3:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected memory with 13-bit signed offset and multiple of 8");
- case Match_MemSImm11:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected memory with 11-bit signed offset");
- case Match_MemSImm12:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected memory with 12-bit signed offset");
- case Match_MemSImm16:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected memory with 16-bit signed offset");
- case Match_MemSImmPtr:
- return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
- "expected memory with 32-bit signed offset");
- case Match_RequiresPosSizeRange0_32: {
- SMLoc ErrorStart = Operands[3]->getStartLoc();
- SMLoc ErrorEnd = Operands[4]->getEndLoc();
- return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
- SMRange(ErrorStart, ErrorEnd));
- }
- case Match_RequiresPosSizeUImm6: {
- SMLoc ErrorStart = Operands[3]->getStartLoc();
- SMLoc ErrorEnd = Operands[4]->getEndLoc();
- return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
- SMRange(ErrorStart, ErrorEnd));
- }
- case Match_RequiresPosSizeRange33_64: {
- SMLoc ErrorStart = Operands[3]->getStartLoc();
- SMLoc ErrorEnd = Operands[4]->getEndLoc();
- return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
- SMRange(ErrorStart, ErrorEnd));
- }
}
llvm_unreachable("Implement any new match types added!");
@@ -5516,17 +3684,6 @@ void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
Warning(Loc, "macro instruction expanded into multiple instructions");
}
-void MipsAsmParser::ConvertXWPOperands(MCInst &Inst,
- const OperandVector &Operands) {
- assert(
- (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) &&
- "Unexpected instruction!");
- ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1);
- int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg());
- Inst.addOperand(MCOperand::createReg(NextReg));
- ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2);
-}
-
void
MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
SMRange Range, bool ShowColors) {
@@ -5540,7 +3697,7 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) {
CC = StringSwitch<unsigned>(Name)
.Case("zero", 0)
- .Cases("at", "AT", 1)
+ .Case("at", 1)
.Case("a0", 4)
.Case("a1", 5)
.Case("a2", 6)
@@ -5628,6 +3785,7 @@ int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
}
int MipsAsmParser::matchFPURegisterName(StringRef Name) {
+
if (Name[0] == 'f') {
StringRef NumString = Name.substr(1);
unsigned IntVal;
@@ -5641,6 +3799,7 @@ int MipsAsmParser::matchFPURegisterName(StringRef Name) {
}
int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
+
if (Name.startswith("fcc")) {
StringRef NumString = Name.substr(3);
unsigned IntVal;
@@ -5654,6 +3813,7 @@ int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
}
int MipsAsmParser::matchACRegisterName(StringRef Name) {
+
if (Name.startswith("ac")) {
StringRef NumString = Name.substr(2);
unsigned IntVal;
@@ -5695,10 +3855,6 @@ int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
return CC;
}
-bool MipsAsmParser::canUseATReg() {
- return AssemblerOptions.back()->getATRegIndex() != 0;
-}
-
unsigned MipsAsmParser::getATReg(SMLoc Loc) {
unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
if (ATIndex == 0) {
@@ -5715,9 +3871,22 @@ unsigned MipsAsmParser::getReg(int RC, int RegNo) {
return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
}
+unsigned MipsAsmParser::getGPR(int RegNo) {
+ return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
+ RegNo);
+}
+
+int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
+ if (RegNum >
+ getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
+ return -1;
+
+ return getReg(RegClass, RegNum);
+}
+
bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
MCAsmParser &Parser = getParser();
- LLVM_DEBUG(dbgs() << "parseOperand\n");
+ 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.
@@ -5730,9 +3899,12 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
if (ResTy == MatchOperand_ParseFail)
return true;
- LLVM_DEBUG(dbgs() << ".. Generic Parser\n");
+ DEBUG(dbgs() << ".. Generic Parser\n");
switch (getLexer().getKind()) {
+ default:
+ Error(Parser.getTok().getLoc(), "unexpected token in operand");
+ return true;
case AsmToken::Dollar: {
// Parse the register.
SMLoc S = Parser.getTok().getLoc();
@@ -5759,35 +3931,107 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
return false;
}
- default: {
- LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
-
- const MCExpr *Expr;
+ // Else drop to expression parsing.
+ case AsmToken::LParen:
+ case AsmToken::Minus:
+ case AsmToken::Plus:
+ case AsmToken::Integer:
+ case AsmToken::Tilde:
+ case AsmToken::String: {
+ DEBUG(dbgs() << ".. generic integer\n");
+ OperandMatchResultTy ResTy = parseImm(Operands);
+ return ResTy != MatchOperand_Success;
+ }
+ case AsmToken::Percent: {
+ // It is a symbol reference or constant expression.
+ const MCExpr *IdVal;
SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
- if (getParser().parseExpression(Expr))
+ if (parseRelocOperand(IdVal))
return true;
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
+ Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
return false;
- }
+ } // case AsmToken::Percent
} // switch(getLexer().getKind())
return true;
}
+const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
+ StringRef RelocStr) {
+ const MCExpr *Res;
+ // Check the type of the expression.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
+ // It's a constant, evaluate reloc value.
+ int16_t Val;
+ switch (getVariantKind(RelocStr)) {
+ case MCSymbolRefExpr::VK_Mips_ABS_LO:
+ // Get the 1st 16-bits.
+ Val = MCE->getValue() & 0xffff;
+ break;
+ case MCSymbolRefExpr::VK_Mips_ABS_HI:
+ // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
+ // 16 bits being negative.
+ Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
+ break;
+ case MCSymbolRefExpr::VK_Mips_HIGHER:
+ // Get the 3rd 16-bits.
+ Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
+ break;
+ case MCSymbolRefExpr::VK_Mips_HIGHEST:
+ // Get the 4th 16-bits.
+ Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
+ break;
+ default:
+ report_fatal_error("unsupported reloc value");
+ }
+ return MCConstantExpr::create(Val, getContext());
+ }
+
+ if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
+ // It's a symbol, create a symbolic expression from the symbol.
+ const MCSymbol *Symbol = &MSRE->getSymbol();
+ MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
+ Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
+ return Res;
+ }
+
+ if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
+ MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
+
+ // Try to create target expression.
+ if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
+ return MipsMCExpr::create(VK, Expr, getContext());
+
+ const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
+ const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
+ Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
+ return Res;
+ }
+
+ if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
+ const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
+ Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
+ return Res;
+ }
+ // Just return the original expression.
+ return Expr;
+}
+
bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
+
switch (Expr->getKind()) {
case MCExpr::Constant:
return true;
case MCExpr::SymbolRef:
return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
- case MCExpr::Binary: {
- const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
- if (!isEvaluated(BE->getLHS()))
- return false;
- return isEvaluated(BE->getRHS());
- }
+ case MCExpr::Binary:
+ if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
+ if (!isEvaluated(BE->getLHS()))
+ return false;
+ return isEvaluated(BE->getRHS());
+ }
case MCExpr::Unary:
return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
case MCExpr::Target:
@@ -5796,6 +4040,49 @@ bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
return false;
}
+bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
+ MCAsmParser &Parser = getParser();
+ Parser.Lex(); // Eat the % token.
+ const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
+ if (Tok.isNot(AsmToken::Identifier))
+ return true;
+
+ std::string Str = Tok.getIdentifier();
+
+ Parser.Lex(); // Eat the identifier.
+ // Now make an expression from the rest of the operand.
+ const MCExpr *IdVal;
+ SMLoc EndLoc;
+
+ if (getLexer().getKind() == AsmToken::LParen) {
+ while (1) {
+ Parser.Lex(); // Eat the '(' token.
+ if (getLexer().getKind() == AsmToken::Percent) {
+ Parser.Lex(); // Eat the % token.
+ const AsmToken &nextTok = Parser.getTok();
+ if (nextTok.isNot(AsmToken::Identifier))
+ return true;
+ Str += "(%";
+ Str += nextTok.getIdentifier();
+ Parser.Lex(); // Eat the identifier.
+ if (getLexer().getKind() != AsmToken::LParen)
+ return true;
+ } else
+ break;
+ }
+ if (getParser().parseParenExpression(IdVal, EndLoc))
+ return true;
+
+ while (getLexer().getKind() == AsmToken::RParen)
+ Parser.Lex(); // Eat the ')' token.
+
+ } else
+ return true; // Parenthesis must follow the relocation operand.
+
+ Res = evaluateRelocExpr(IdVal, Str);
+ return false;
+}
+
bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) {
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
@@ -5823,21 +4110,45 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
}
bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
+ MCAsmParser &Parser = getParser();
SMLoc S;
+ bool Result = true;
+ unsigned NumOfLParen = 0;
- if (isParenExpr)
- return getParser().parseParenExprOfDepth(0, Res, S);
- return getParser().parseExpression(Res);
+ while (getLexer().getKind() == AsmToken::LParen) {
+ Parser.Lex();
+ ++NumOfLParen;
+ }
+
+ switch (getLexer().getKind()) {
+ default:
+ return true;
+ case AsmToken::Identifier:
+ case AsmToken::LParen:
+ case AsmToken::Integer:
+ case AsmToken::Minus:
+ case AsmToken::Plus:
+ if (isParenExpr)
+ Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
+ else
+ Result = (getParser().parseExpression(Res));
+ while (getLexer().getKind() == AsmToken::RParen)
+ Parser.Lex();
+ break;
+ case AsmToken::Percent:
+ Result = parseRelocOperand(Res);
+ }
+ return Result;
}
-OperandMatchResultTy
+MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseMemOperand(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
- LLVM_DEBUG(dbgs() << "parseMemOperand\n");
+ DEBUG(dbgs() << "parseMemOperand\n");
const MCExpr *IdVal = nullptr;
SMLoc S;
bool isParenExpr = false;
- OperandMatchResultTy Res = MatchOperand_NoMatch;
+ MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
// First operand is the offset.
S = Parser.getTok().getLoc();
@@ -5865,66 +4176,14 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) {
// Zero register assumed, add a memory operand with ZERO as its base.
// "Base" will be managed by k_Memory.
- auto Base = MipsOperand::createGPRReg(
- 0, "0", getContext().getRegisterInfo(), S, E, *this);
+ auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
+ S, E, *this);
Operands.push_back(
MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
return MatchOperand_Success;
}
- MCBinaryExpr::Opcode Opcode;
- // GAS and LLVM treat comparison operators different. GAS will generate -1
- // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
- // highly unlikely to be found in a memory offset expression, we don't
- // handle them.
- switch (Tok.getKind()) {
- case AsmToken::Plus:
- Opcode = MCBinaryExpr::Add;
- Parser.Lex();
- break;
- case AsmToken::Minus:
- Opcode = MCBinaryExpr::Sub;
- Parser.Lex();
- break;
- case AsmToken::Star:
- Opcode = MCBinaryExpr::Mul;
- Parser.Lex();
- break;
- case AsmToken::Pipe:
- Opcode = MCBinaryExpr::Or;
- Parser.Lex();
- break;
- case AsmToken::Amp:
- Opcode = MCBinaryExpr::And;
- Parser.Lex();
- break;
- case AsmToken::LessLess:
- Opcode = MCBinaryExpr::Shl;
- Parser.Lex();
- break;
- case AsmToken::GreaterGreater:
- Opcode = MCBinaryExpr::LShr;
- Parser.Lex();
- break;
- case AsmToken::Caret:
- Opcode = MCBinaryExpr::Xor;
- Parser.Lex();
- break;
- case AsmToken::Slash:
- Opcode = MCBinaryExpr::Div;
- Parser.Lex();
- break;
- case AsmToken::Percent:
- Opcode = MCBinaryExpr::Mod;
- Parser.Lex();
- break;
- default:
- Error(Parser.getTok().getLoc(), "'(' or expression expected");
- return MatchOperand_ParseFail;
- }
- const MCExpr * NextExpr;
- if (getParser().parseExpression(NextExpr))
- return MatchOperand_ParseFail;
- IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
+ Error(Parser.getTok().getLoc(), "'(' expected");
+ return MatchOperand_ParseFail;
}
Parser.Lex(); // Eat the '(' token.
@@ -5969,12 +4228,13 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) {
bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
- if (!Sym)
- return false;
-
- SMLoc S = Parser.getTok().getLoc();
- if (Sym->isVariable()) {
- const MCExpr *Expr = Sym->getVariableValue();
+ if (Sym) {
+ SMLoc S = Parser.getTok().getLoc();
+ const MCExpr *Expr;
+ if (Sym->isVariable())
+ Expr = Sym->getVariableValue();
+ else
+ return false;
if (Expr->getKind() == MCExpr::SymbolRef) {
const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
StringRef DefSymbol = Ref->getSymbol().getName();
@@ -5984,146 +4244,120 @@ bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
if (ResTy == MatchOperand_Success) {
Parser.Lex();
return true;
- }
- if (ResTy == MatchOperand_ParseFail)
+ } else if (ResTy == MatchOperand_ParseFail)
llvm_unreachable("Should never ParseFail");
+ return false;
}
- }
- } else if (Sym->isUnset()) {
- // If symbol is unset, it might be created in the `parseSetAssignment`
- // routine as an alias for a numeric register name.
- // Lookup in the aliases list.
- auto Entry = RegisterSets.find(Sym->getName());
- if (Entry != RegisterSets.end()) {
- OperandMatchResultTy ResTy =
- matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S);
- if (ResTy == MatchOperand_Success) {
- Parser.Lex();
- return true;
- }
+ } else if (Expr->getKind() == MCExpr::Constant) {
+ Parser.Lex();
+ const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
+ Operands.push_back(
+ MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
+ return true;
}
}
-
return false;
}
-OperandMatchResultTy
+MipsAsmParser::OperandMatchResultTy
MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
StringRef Identifier,
SMLoc S) {
int Index = matchCPURegisterName(Identifier);
if (Index != -1) {
Operands.push_back(MipsOperand::createGPRReg(
- Index, Identifier, getContext().getRegisterInfo(), S,
- getLexer().getLoc(), *this));
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
Index = matchHWRegsRegisterName(Identifier);
if (Index != -1) {
Operands.push_back(MipsOperand::createHWRegsReg(
- Index, Identifier, getContext().getRegisterInfo(), S,
- getLexer().getLoc(), *this));
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
Index = matchFPURegisterName(Identifier);
if (Index != -1) {
Operands.push_back(MipsOperand::createFGRReg(
- Index, Identifier, getContext().getRegisterInfo(), S,
- getLexer().getLoc(), *this));
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
Index = matchFCCRegisterName(Identifier);
if (Index != -1) {
Operands.push_back(MipsOperand::createFCCReg(
- Index, Identifier, getContext().getRegisterInfo(), S,
- getLexer().getLoc(), *this));
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
Index = matchACRegisterName(Identifier);
if (Index != -1) {
Operands.push_back(MipsOperand::createACCReg(
- Index, Identifier, getContext().getRegisterInfo(), S,
- getLexer().getLoc(), *this));
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
Index = matchMSA128RegisterName(Identifier);
if (Index != -1) {
Operands.push_back(MipsOperand::createMSA128Reg(
- Index, Identifier, getContext().getRegisterInfo(), S,
- getLexer().getLoc(), *this));
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
Index = matchMSA128CtrlRegisterName(Identifier);
if (Index != -1) {
Operands.push_back(MipsOperand::createMSACtrlReg(
- Index, Identifier, getContext().getRegisterInfo(), S,
- getLexer().getLoc(), *this));
+ Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
return MatchOperand_Success;
}
return MatchOperand_NoMatch;
}
-OperandMatchResultTy
-MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands,
- const AsmToken &Token, SMLoc S) {
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
+ MCAsmParser &Parser = getParser();
+ auto Token = Parser.getLexer().peekTok(false);
+
if (Token.is(AsmToken::Identifier)) {
- LLVM_DEBUG(dbgs() << ".. identifier\n");
+ DEBUG(dbgs() << ".. identifier\n");
StringRef Identifier = Token.getIdentifier();
OperandMatchResultTy ResTy =
matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
return ResTy;
} else if (Token.is(AsmToken::Integer)) {
- LLVM_DEBUG(dbgs() << ".. integer\n");
- int64_t RegNum = Token.getIntVal();
- if (RegNum < 0 || RegNum > 31) {
- // Show the error, but treat invalid register
- // number as a normal one to continue parsing
- // and catch other possible errors.
- Error(getLexer().getLoc(), "invalid register number");
- }
+ DEBUG(dbgs() << ".. integer\n");
Operands.push_back(MipsOperand::createNumericReg(
- RegNum, Token.getString(), getContext().getRegisterInfo(), S,
- Token.getLoc(), *this));
+ Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
+ *this));
return MatchOperand_Success;
}
- LLVM_DEBUG(dbgs() << Token.getKind() << "\n");
+ DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
return MatchOperand_NoMatch;
}
-OperandMatchResultTy
-MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
- auto Token = getLexer().peekTok(false);
- return matchAnyRegisterWithoutDollar(Operands, Token, S);
-}
-
-OperandMatchResultTy
+MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
- LLVM_DEBUG(dbgs() << "parseAnyRegister\n");
+ DEBUG(dbgs() << "parseAnyRegister\n");
auto Token = Parser.getTok();
SMLoc S = Token.getLoc();
if (Token.isNot(AsmToken::Dollar)) {
- LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
+ DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
if (Token.is(AsmToken::Identifier)) {
if (searchSymbolAlias(Operands))
return MatchOperand_Success;
}
- LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
+ DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
return MatchOperand_NoMatch;
}
- LLVM_DEBUG(dbgs() << ".. $\n");
+ DEBUG(dbgs() << ".. $\n");
OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
if (ResTy == MatchOperand_Success) {
@@ -6133,19 +4367,48 @@ MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
return ResTy;
}
-OperandMatchResultTy
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseImm(OperandVector &Operands) {
+ MCAsmParser &Parser = getParser();
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_NoMatch;
+ case AsmToken::LParen:
+ case AsmToken::Minus:
+ case AsmToken::Plus:
+ case AsmToken::Integer:
+ case AsmToken::Tilde:
+ case AsmToken::String:
+ break;
+ }
+
+ const MCExpr *IdVal;
+ SMLoc S = Parser.getTok().getLoc();
+ if (getParser().parseExpression(IdVal))
+ return MatchOperand_ParseFail;
+
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
+ return MatchOperand_Success;
+}
+
+MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
- LLVM_DEBUG(dbgs() << "parseJumpTarget\n");
+ DEBUG(dbgs() << "parseJumpTarget\n");
SMLoc S = getLexer().getLoc();
+ // Integers and expressions are acceptable
+ OperandMatchResultTy ResTy = parseImm(Operands);
+ if (ResTy != MatchOperand_NoMatch)
+ return ResTy;
+
// Registers are a valid target and have priority over symbols.
- OperandMatchResultTy ResTy = parseAnyRegister(Operands);
+ ResTy = parseAnyRegister(Operands);
if (ResTy != MatchOperand_NoMatch)
return ResTy;
- // Integers and expressions are acceptable
const MCExpr *Expr = nullptr;
if (Parser.parseExpression(Expr)) {
// We have no way of knowing if a symbol was consumed so we must ParseFail
@@ -6156,25 +4419,18 @@ MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
return MatchOperand_Success;
}
-OperandMatchResultTy
+MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseInvNum(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
const MCExpr *IdVal;
- // If the first token is '$' we may have register operand. We have to reject
- // cases where it is not a register. Complicating the matter is that
- // register names are not reserved across all ABIs.
- // Peek past the dollar to see if it's a register name for this ABI.
+ // If the first token is '$' we may have register operand.
+ if (Parser.getTok().is(AsmToken::Dollar))
+ return MatchOperand_NoMatch;
SMLoc S = Parser.getTok().getLoc();
- if (Parser.getTok().is(AsmToken::Dollar)) {
- return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
- ? MatchOperand_ParseFail
- : MatchOperand_NoMatch;
- }
if (getParser().parseExpression(IdVal))
return MatchOperand_ParseFail;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
- if (!MCE)
- return MatchOperand_NoMatch;
+ assert(MCE && "Unexpected MCExpr type.");
int64_t Val = MCE->getValue();
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Operands.push_back(MipsOperand::CreateImm(
@@ -6182,7 +4438,47 @@ MipsAsmParser::parseInvNum(OperandVector &Operands) {
return MatchOperand_Success;
}
-OperandMatchResultTy
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseLSAImm(OperandVector &Operands) {
+ MCAsmParser &Parser = getParser();
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_NoMatch;
+ case AsmToken::LParen:
+ case AsmToken::Plus:
+ case AsmToken::Minus:
+ case AsmToken::Integer:
+ break;
+ }
+
+ const MCExpr *Expr;
+ SMLoc S = Parser.getTok().getLoc();
+
+ if (getParser().parseExpression(Expr))
+ return MatchOperand_ParseFail;
+
+ int64_t Val;
+ if (!Expr->evaluateAsAbsolute(Val)) {
+ Error(S, "expected immediate value");
+ return MatchOperand_ParseFail;
+ }
+
+ // The LSA instruction allows a 2-bit unsigned immediate. For this reason
+ // and because the CPU always adds one to the immediate field, the allowed
+ // range becomes 1..4. We'll only check the range here and will deal
+ // with the addition/subtraction when actually decoding/encoding
+ // the instruction.
+ if (Val < 1 || Val > 4) {
+ Error(S, "immediate not in range (1..4)");
+ return MatchOperand_ParseFail;
+ }
+
+ Operands.push_back(
+ MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
+ return MatchOperand_Success;
+}
+
+MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseRegisterList(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
SmallVector<unsigned, 10> Regs;
@@ -6268,6 +4564,97 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) {
return MatchOperand_Success;
}
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
+ MCAsmParser &Parser = getParser();
+
+ SMLoc S = Parser.getTok().getLoc();
+ if (parseAnyRegister(Operands) != MatchOperand_Success)
+ return MatchOperand_ParseFail;
+
+ SMLoc E = Parser.getTok().getLoc();
+ MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
+ unsigned Reg = Op.getGPR32Reg();
+ Operands.pop_back();
+ Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
+ return MatchOperand_Success;
+}
+
+MipsAsmParser::OperandMatchResultTy
+MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
+ MCAsmParser &Parser = getParser();
+ SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
+ SmallVector<unsigned, 10> Regs;
+
+ if (Parser.getTok().isNot(AsmToken::Dollar))
+ return MatchOperand_ParseFail;
+
+ SMLoc S = Parser.getTok().getLoc();
+
+ if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
+ return MatchOperand_ParseFail;
+
+ MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
+ unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
+ Regs.push_back(RegNo);
+
+ SMLoc E = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::Comma)) {
+ Error(E, "',' expected");
+ return MatchOperand_ParseFail;
+ }
+
+ // Remove comma.
+ Parser.Lex();
+
+ if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
+ return MatchOperand_ParseFail;
+
+ Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
+ RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
+ Regs.push_back(RegNo);
+
+ Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
+
+ return MatchOperand_Success;
+}
+
+MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
+
+ MCSymbolRefExpr::VariantKind VK =
+ StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
+ .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
+ .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
+ .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
+ .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
+ .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
+ .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
+ .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
+ .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
+ .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
+ .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
+ .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
+ .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
+ .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
+ .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
+ .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
+ .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
+ .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
+ .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
+ .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
+ .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
+ .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
+ .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
+ .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
+ .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
+ .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
+ .Default(MCSymbolRefExpr::VK_None);
+
+ assert(VK != MCSymbolRefExpr::VK_None);
+
+ return VK;
+}
+
/// Sometimes (i.e. load/stores) the operand may be followed immediately by
/// either this.
/// ::= '(', register, ')'
@@ -6281,10 +4668,12 @@ bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
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(
@@ -6309,10 +4698,12 @@ bool MipsAsmParser::parseBracketSuffix(StringRef Name,
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(
@@ -6322,22 +4713,18 @@ bool MipsAsmParser::parseBracketSuffix(StringRef Name,
return false;
}
-static std::string MipsMnemonicSpellCheck(StringRef S, uint64_t FBS,
- unsigned VariantID = 0);
-
bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) {
MCAsmParser &Parser = getParser();
- LLVM_DEBUG(dbgs() << "ParseInstruction\n");
+ DEBUG(dbgs() << "ParseInstruction\n");
// We have reached first instruction, module directive are now forbidden.
getTargetStreamer().forbidModuleDirective();
// Check if we have valid mnemonic
if (!mnemonicIsValid(Name, 0)) {
- uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
- std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS);
- return Error(NameLoc, "unknown instruction" + Suggestion);
+ Parser.eatToEndOfStatement();
+ return Error(NameLoc, "unknown instruction");
}
// First operand in MCInst is instruction mnemonic.
Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
@@ -6347,6 +4734,7 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
// Read the first operand.
if (parseOperand(Operands, Name)) {
SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
}
if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
@@ -6358,6 +4746,7 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
// Parse and remember the operand.
if (parseOperand(Operands, Name)) {
SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
}
// Parse bracket and parenthesis suffixes before we iterate
@@ -6371,16 +4760,17 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
}
if (getLexer().isNot(AsmToken::EndOfStatement)) {
SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
}
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
-// FIXME: Given that these have the same name, these should both be
-// consistent on affecting the Parser.
bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
+ MCAsmParser &Parser = getParser();
SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
return Error(Loc, ErrorMsg);
}
@@ -6659,90 +5049,6 @@ bool MipsAsmParser::parseSetNoOddSPRegDirective() {
return false;
}
-bool MipsAsmParser::parseSetMtDirective() {
- MCAsmParser &Parser = getParser();
- Parser.Lex(); // Eat "mt".
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- setFeatureBits(Mips::FeatureMT, "mt");
- getTargetStreamer().emitDirectiveSetMt();
- Parser.Lex(); // Consume the EndOfStatement.
- return false;
-}
-
-bool MipsAsmParser::parseSetNoMtDirective() {
- MCAsmParser &Parser = getParser();
- Parser.Lex(); // Eat "nomt".
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- clearFeatureBits(Mips::FeatureMT, "mt");
-
- getTargetStreamer().emitDirectiveSetNoMt();
- Parser.Lex(); // Consume the EndOfStatement.
- return false;
-}
-
-bool MipsAsmParser::parseSetNoCRCDirective() {
- MCAsmParser &Parser = getParser();
- Parser.Lex(); // Eat "nocrc".
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- clearFeatureBits(Mips::FeatureCRC, "crc");
-
- getTargetStreamer().emitDirectiveSetNoCRC();
- Parser.Lex(); // Consume the EndOfStatement.
- return false;
-}
-
-bool MipsAsmParser::parseSetNoVirtDirective() {
- MCAsmParser &Parser = getParser();
- Parser.Lex(); // Eat "novirt".
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- clearFeatureBits(Mips::FeatureVirt, "virt");
-
- getTargetStreamer().emitDirectiveSetNoVirt();
- Parser.Lex(); // Consume the EndOfStatement.
- return false;
-}
-
-bool MipsAsmParser::parseSetNoGINVDirective() {
- MCAsmParser &Parser = getParser();
- Parser.Lex(); // Eat "noginv".
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- clearFeatureBits(Mips::FeatureGINV, "ginv");
-
- getTargetStreamer().emitDirectiveSetNoGINV();
- Parser.Lex(); // Consume the EndOfStatement.
- return false;
-}
-
bool MipsAsmParser::parseSetPopDirective() {
MCAsmParser &Parser = getParser();
SMLoc Loc = getLexer().getLoc();
@@ -6774,7 +5080,7 @@ bool MipsAsmParser::parseSetPushDirective() {
// Create a copy of the current assembler options environment and push it.
AssemblerOptions.push_back(
- llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
+ make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
getTargetStreamer().emitDirectiveSetPush();
return false;
@@ -6808,30 +5114,17 @@ bool MipsAsmParser::parseSetAssignment() {
MCAsmParser &Parser = getParser();
if (Parser.parseIdentifier(Name))
- return reportParseError("expected identifier after .set");
+ reportParseError("expected identifier after .set");
if (getLexer().isNot(AsmToken::Comma))
return reportParseError("unexpected token, expected comma");
Lex(); // Eat comma
- if (getLexer().is(AsmToken::Dollar) &&
- getLexer().peekTok().is(AsmToken::Integer)) {
- // Parse assignment of a numeric register:
- // .set r1,$1
- Parser.Lex(); // Eat $.
- RegisterSets[Name] = Parser.getTok();
- Parser.Lex(); // Eat identifier.
- getContext().getOrCreateSymbol(Name);
- } else if (!Parser.parseExpression(Value)) {
- // Parse assignment of an expression including
- // symbolic registers:
- // .set $tmp, $BB0-$BB1
- // .set r2, $f2
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- Sym->setVariableValue(Value);
- } else {
+ if (Parser.parseExpression(Value))
return reportParseError("expected valid expression after comma");
- }
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ Sym->setVariableValue(Value);
return false;
}
@@ -6881,16 +5174,13 @@ bool MipsAsmParser::parseSetArchDirective() {
.Case("mips64r3", "mips64r3")
.Case("mips64r5", "mips64r5")
.Case("mips64r6", "mips64r6")
- .Case("octeon", "cnmips")
+ .Case("cnmips", "cnmips")
.Case("r4000", "mips3") // This is an implementation of Mips3.
.Default("");
if (ArchFeatureName.empty())
return reportParseError("unsupported architecture");
- if (ArchFeatureName == "mips64r6" && inMicroMipsMode())
- return reportParseError("mips64r6 does not support microMIPS");
-
selectArch(ArchFeatureName);
getTargetStreamer().emitDirectiveSetArch(Arch);
return false;
@@ -6909,12 +5199,7 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
setFeatureBits(Mips::FeatureDSP, "dsp");
getTargetStreamer().emitDirectiveSetDsp();
break;
- case Mips::FeatureDSPR2:
- setFeatureBits(Mips::FeatureDSPR2, "dspr2");
- getTargetStreamer().emitDirectiveSetDspr2();
- break;
case Mips::FeatureMicroMips:
- setFeatureBits(Mips::FeatureMicroMips, "micromips");
getTargetStreamer().emitDirectiveSetMicroMips();
break;
case Mips::FeatureMips1:
@@ -6977,18 +5262,6 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
selectArch("mips64r6");
getTargetStreamer().emitDirectiveSetMips64R6();
break;
- case Mips::FeatureCRC:
- setFeatureBits(Mips::FeatureCRC, "crc");
- getTargetStreamer().emitDirectiveSetCRC();
- break;
- case Mips::FeatureVirt:
- setFeatureBits(Mips::FeatureVirt, "virt");
- getTargetStreamer().emitDirectiveSetVirt();
- break;
- case Mips::FeatureGINV:
- setFeatureBits(Mips::FeatureGINV, "ginv");
- getTargetStreamer().emitDirectiveSetGINV();
- break;
}
return false;
}
@@ -6997,6 +5270,7 @@ bool MipsAsmParser::eatComma(StringRef ErrorStr) {
MCAsmParser &Parser = getParser();
if (getLexer().isNot(AsmToken::Comma)) {
SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
return Error(Loc, ErrorStr);
}
@@ -7082,9 +5356,12 @@ bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
return false;
}
- if (!getTargetStreamer().emitDirectiveCpRestore(
- CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
- return true;
+ // Store the $gp on the stack.
+ SmallVector<MCInst, 3> StoreInsts;
+ createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
+ StoreInsts);
+
+ getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
@@ -7099,12 +5376,14 @@ bool MipsAsmParser::parseDirectiveCPSetup() {
OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
if (ResTy == MatchOperand_NoMatch) {
reportParseError("expected register containing function address");
+ Parser.eatToEndOfStatement();
return false;
}
MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
if (!FuncRegOpnd.isGPRAsmReg()) {
reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
+ Parser.eatToEndOfStatement();
return false;
}
@@ -7123,6 +5402,7 @@ bool MipsAsmParser::parseDirectiveCPSetup() {
if (Parser.parseExpression(OffsetExpr) ||
!OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
reportParseError(ExprLoc, "expected save register or stack offset");
+ Parser.eatToEndOfStatement();
return false;
}
@@ -7132,6 +5412,7 @@ bool MipsAsmParser::parseDirectiveCPSetup() {
MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
if (!SaveOpnd.isGPRAsmReg()) {
reportParseError(SaveOpnd.getStartLoc(), "invalid register");
+ Parser.eatToEndOfStatement();
return false;
}
Save = SaveOpnd.getGPR32Reg();
@@ -7188,131 +5469,120 @@ bool MipsAsmParser::parseDirectiveNaN() {
}
bool MipsAsmParser::parseDirectiveSet() {
- const AsmToken &Tok = getParser().getTok();
- StringRef IdVal = Tok.getString();
- SMLoc Loc = Tok.getLoc();
+ MCAsmParser &Parser = getParser();
+ // Get the next token.
+ const AsmToken &Tok = Parser.getTok();
- if (IdVal == "noat")
+ if (Tok.getString() == "noat") {
return parseSetNoAtDirective();
- if (IdVal == "at")
+ } else if (Tok.getString() == "at") {
return parseSetAtDirective();
- if (IdVal == "arch")
+ } else if (Tok.getString() == "arch") {
return parseSetArchDirective();
- if (IdVal == "bopt") {
- Warning(Loc, "'bopt' feature is unsupported");
- getParser().Lex();
- return false;
- }
- if (IdVal == "nobopt") {
- // We're already running in nobopt mode, so nothing to do.
- getParser().Lex();
- return false;
- }
- if (IdVal == "fp")
+ } else if (Tok.getString() == "fp") {
return parseSetFpDirective();
- if (IdVal == "oddspreg")
+ } else if (Tok.getString() == "oddspreg") {
return parseSetOddSPRegDirective();
- if (IdVal == "nooddspreg")
+ } else if (Tok.getString() == "nooddspreg") {
return parseSetNoOddSPRegDirective();
- if (IdVal == "pop")
+ } else if (Tok.getString() == "pop") {
return parseSetPopDirective();
- if (IdVal == "push")
+ } else if (Tok.getString() == "push") {
return parseSetPushDirective();
- if (IdVal == "reorder")
+ } else if (Tok.getString() == "reorder") {
return parseSetReorderDirective();
- if (IdVal == "noreorder")
+ } else if (Tok.getString() == "noreorder") {
return parseSetNoReorderDirective();
- if (IdVal == "macro")
+ } else if (Tok.getString() == "macro") {
return parseSetMacroDirective();
- if (IdVal == "nomacro")
+ } else if (Tok.getString() == "nomacro") {
return parseSetNoMacroDirective();
- if (IdVal == "mips16")
+ } else if (Tok.getString() == "mips16") {
return parseSetMips16Directive();
- if (IdVal == "nomips16")
+ } else if (Tok.getString() == "nomips16") {
return parseSetNoMips16Directive();
- if (IdVal == "nomicromips") {
- clearFeatureBits(Mips::FeatureMicroMips, "micromips");
+ } else if (Tok.getString() == "nomicromips") {
getTargetStreamer().emitDirectiveSetNoMicroMips();
- getParser().eatToEndOfStatement();
+ Parser.eatToEndOfStatement();
return false;
- }
- if (IdVal == "micromips") {
- if (hasMips64r6()) {
- Error(Loc, ".set micromips directive is not supported with MIPS64R6");
- return false;
- }
+ } else if (Tok.getString() == "micromips") {
return parseSetFeature(Mips::FeatureMicroMips);
- }
- if (IdVal == "mips0")
+ } else if (Tok.getString() == "mips0") {
return parseSetMips0Directive();
- if (IdVal == "mips1")
+ } else if (Tok.getString() == "mips1") {
return parseSetFeature(Mips::FeatureMips1);
- if (IdVal == "mips2")
+ } else if (Tok.getString() == "mips2") {
return parseSetFeature(Mips::FeatureMips2);
- if (IdVal == "mips3")
+ } else if (Tok.getString() == "mips3") {
return parseSetFeature(Mips::FeatureMips3);
- if (IdVal == "mips4")
+ } else if (Tok.getString() == "mips4") {
return parseSetFeature(Mips::FeatureMips4);
- if (IdVal == "mips5")
+ } else if (Tok.getString() == "mips5") {
return parseSetFeature(Mips::FeatureMips5);
- if (IdVal == "mips32")
+ } else if (Tok.getString() == "mips32") {
return parseSetFeature(Mips::FeatureMips32);
- if (IdVal == "mips32r2")
+ } else if (Tok.getString() == "mips32r2") {
return parseSetFeature(Mips::FeatureMips32r2);
- if (IdVal == "mips32r3")
+ } else if (Tok.getString() == "mips32r3") {
return parseSetFeature(Mips::FeatureMips32r3);
- if (IdVal == "mips32r5")
+ } else if (Tok.getString() == "mips32r5") {
return parseSetFeature(Mips::FeatureMips32r5);
- if (IdVal == "mips32r6")
+ } else if (Tok.getString() == "mips32r6") {
return parseSetFeature(Mips::FeatureMips32r6);
- if (IdVal == "mips64")
+ } else if (Tok.getString() == "mips64") {
return parseSetFeature(Mips::FeatureMips64);
- if (IdVal == "mips64r2")
+ } else if (Tok.getString() == "mips64r2") {
return parseSetFeature(Mips::FeatureMips64r2);
- if (IdVal == "mips64r3")
+ } else if (Tok.getString() == "mips64r3") {
return parseSetFeature(Mips::FeatureMips64r3);
- if (IdVal == "mips64r5")
+ } else if (Tok.getString() == "mips64r5") {
return parseSetFeature(Mips::FeatureMips64r5);
- if (IdVal == "mips64r6") {
- if (inMicroMipsMode()) {
- Error(Loc, "MIPS64R6 is not supported with microMIPS");
- return false;
- }
+ } else if (Tok.getString() == "mips64r6") {
return parseSetFeature(Mips::FeatureMips64r6);
- }
- if (IdVal == "dsp")
+ } else if (Tok.getString() == "dsp") {
return parseSetFeature(Mips::FeatureDSP);
- if (IdVal == "dspr2")
- return parseSetFeature(Mips::FeatureDSPR2);
- if (IdVal == "nodsp")
+ } else if (Tok.getString() == "nodsp") {
return parseSetNoDspDirective();
- if (IdVal == "msa")
+ } else if (Tok.getString() == "msa") {
return parseSetMsaDirective();
- if (IdVal == "nomsa")
+ } else if (Tok.getString() == "nomsa") {
return parseSetNoMsaDirective();
- if (IdVal == "mt")
- return parseSetMtDirective();
- if (IdVal == "nomt")
- return parseSetNoMtDirective();
- if (IdVal == "softfloat")
+ } else if (Tok.getString() == "softfloat") {
return parseSetSoftFloatDirective();
- if (IdVal == "hardfloat")
+ } else if (Tok.getString() == "hardfloat") {
return parseSetHardFloatDirective();
- if (IdVal == "crc")
- return parseSetFeature(Mips::FeatureCRC);
- if (IdVal == "nocrc")
- return parseSetNoCRCDirective();
- if (IdVal == "virt")
- return parseSetFeature(Mips::FeatureVirt);
- if (IdVal == "novirt")
- return parseSetNoVirtDirective();
- if (IdVal == "ginv")
- return parseSetFeature(Mips::FeatureGINV);
- if (IdVal == "noginv")
- return parseSetNoGINVDirective();
-
- // It is just an identifier, look for an assignment.
- return parseSetAssignment();
+ } else {
+ // It is just an identifier, look for an assignment.
+ parseSetAssignment();
+ return false;
+ }
+
+ return true;
+}
+
+/// parseDataDirective
+/// ::= .word [ expression (, expression)* ]
+bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
+ MCAsmParser &Parser = getParser();
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ for (;;) {
+ const MCExpr *Value;
+ if (getParser().parseExpression(Value))
+ return true;
+
+ getParser().getStreamer().EmitValue(Value, Size);
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return Error(L, "unexpected token, expected comma");
+ Parser.Lex();
+ }
+ }
+
+ Parser.Lex();
+ return false;
}
/// parseDirectiveGpWord
@@ -7327,7 +5597,7 @@ bool MipsAsmParser::parseDirectiveGpWord() {
getParser().getStreamer().EmitGPRel32Value(Value);
if (getLexer().isNot(AsmToken::EndOfStatement))
- return Error(getLexer().getLoc(),
+ return Error(getLexer().getLoc(),
"unexpected token, expected end of statement");
Parser.Lex(); // Eat EndOfStatement token.
return false;
@@ -7345,79 +5615,7 @@ bool MipsAsmParser::parseDirectiveGpDWord() {
getParser().getStreamer().EmitGPRel64Value(Value);
if (getLexer().isNot(AsmToken::EndOfStatement))
- return Error(getLexer().getLoc(),
- "unexpected token, expected end of statement");
- Parser.Lex(); // Eat EndOfStatement token.
- return false;
-}
-
-/// parseDirectiveDtpRelWord
-/// ::= .dtprelword tls_sym
-bool MipsAsmParser::parseDirectiveDtpRelWord() {
- MCAsmParser &Parser = getParser();
- const MCExpr *Value;
- // EmitDTPRel32Value requires an expression, so we are using base class
- // method to evaluate the expression.
- if (getParser().parseExpression(Value))
- return true;
- getParser().getStreamer().EmitDTPRel32Value(Value);
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return Error(getLexer().getLoc(),
- "unexpected token, expected end of statement");
- Parser.Lex(); // Eat EndOfStatement token.
- return false;
-}
-
-/// parseDirectiveDtpRelDWord
-/// ::= .dtpreldword tls_sym
-bool MipsAsmParser::parseDirectiveDtpRelDWord() {
- MCAsmParser &Parser = getParser();
- const MCExpr *Value;
- // EmitDTPRel64Value requires an expression, so we are using base class
- // method to evaluate the expression.
- if (getParser().parseExpression(Value))
- return true;
- getParser().getStreamer().EmitDTPRel64Value(Value);
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return Error(getLexer().getLoc(),
- "unexpected token, expected end of statement");
- Parser.Lex(); // Eat EndOfStatement token.
- return false;
-}
-
-/// parseDirectiveTpRelWord
-/// ::= .tprelword tls_sym
-bool MipsAsmParser::parseDirectiveTpRelWord() {
- MCAsmParser &Parser = getParser();
- const MCExpr *Value;
- // EmitTPRel32Value requires an expression, so we are using base class
- // method to evaluate the expression.
- if (getParser().parseExpression(Value))
- return true;
- getParser().getStreamer().EmitTPRel32Value(Value);
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return Error(getLexer().getLoc(),
- "unexpected token, expected end of statement");
- Parser.Lex(); // Eat EndOfStatement token.
- return false;
-}
-
-/// parseDirectiveTpRelDWord
-/// ::= .tpreldword tls_sym
-bool MipsAsmParser::parseDirectiveTpRelDWord() {
- MCAsmParser &Parser = getParser();
- const MCExpr *Value;
- // EmitTPRel64Value requires an expression, so we are using base class
- // method to evaluate the expression.
- if (getParser().parseExpression(Value))
- return true;
- getParser().getStreamer().EmitTPRel64Value(Value);
-
- if (getLexer().isNot(AsmToken::EndOfStatement))
- return Error(getLexer().getLoc(),
+ return Error(getLexer().getLoc(),
"unexpected token, expected end of statement");
Parser.Lex(); // Eat EndOfStatement token.
return false;
@@ -7429,8 +5627,9 @@ bool MipsAsmParser::parseDirectiveOption() {
AsmToken Tok = Parser.getTok();
// At the moment only identifiers are supported.
if (Tok.isNot(AsmToken::Identifier)) {
- return Error(Parser.getTok().getLoc(),
- "unexpected token, expected identifier");
+ Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
+ Parser.eatToEndOfStatement();
+ return false;
}
StringRef Option = Tok.getIdentifier();
@@ -7442,8 +5641,9 @@ bool MipsAsmParser::parseDirectiveOption() {
getTargetStreamer().emitDirectiveOptionPic0();
Parser.Lex();
if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
- return Error(Parser.getTok().getLoc(),
- "unexpected token, expected end of statement");
+ Error(Parser.getTok().getLoc(),
+ "unexpected token, expected end of statement");
+ Parser.eatToEndOfStatement();
}
return false;
}
@@ -7455,14 +5655,15 @@ bool MipsAsmParser::parseDirectiveOption() {
getTargetStreamer().emitDirectiveOptionPic2();
Parser.Lex();
if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
- return Error(Parser.getTok().getLoc(),
- "unexpected token, expected end of statement");
+ Error(Parser.getTok().getLoc(),
+ "unexpected token, expected end of statement");
+ Parser.eatToEndOfStatement();
}
return false;
}
// Unknown option.
- Warning(Parser.getTok().getLoc(),
+ Warning(Parser.getTok().getLoc(),
"unknown option, expected 'pic0' or 'pic2'");
Parser.eatToEndOfStatement();
return false;
@@ -7485,54 +5686,12 @@ bool MipsAsmParser::parseInsnDirective() {
return false;
}
-/// parseRSectionDirective
-/// ::= .rdata
-bool MipsAsmParser::parseRSectionDirective(StringRef Section) {
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- MCSection *ELFSection = getContext().getELFSection(
- Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
- getParser().getStreamer().SwitchSection(ELFSection);
-
- getParser().Lex(); // Eat EndOfStatement token.
- return false;
-}
-
-/// parseSSectionDirective
-/// ::= .sbss
-/// ::= .sdata
-bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- MCSection *ELFSection = getContext().getELFSection(
- Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
- getParser().getStreamer().SwitchSection(ELFSection);
-
- getParser().Lex(); // Eat EndOfStatement token.
- return false;
-}
-
/// parseDirectiveModule
/// ::= .module oddspreg
/// ::= .module nooddspreg
/// ::= .module fp=value
/// ::= .module softfloat
/// ::= .module hardfloat
-/// ::= .module mt
-/// ::= .module crc
-/// ::= .module nocrc
-/// ::= .module virt
-/// ::= .module novirt
-/// ::= .module ginv
-/// ::= .module noginv
bool MipsAsmParser::parseDirectiveModule() {
MCAsmParser &Parser = getParser();
MCAsmLexer &Lexer = getLexer();
@@ -7571,7 +5730,8 @@ bool MipsAsmParser::parseDirectiveModule() {
return false; // parseDirectiveModule has finished successfully.
} else if (Option == "nooddspreg") {
if (!isABI_O32()) {
- return Error(L, "'.module nooddspreg' requires the O32 ABI");
+ Error(L, "'.module nooddspreg' requires the O32 ABI");
+ return false;
}
setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
@@ -7632,139 +5792,6 @@ bool MipsAsmParser::parseDirectiveModule() {
}
return false; // parseDirectiveModule has finished successfully.
- } else if (Option == "mt") {
- setModuleFeatureBits(Mips::FeatureMT, "mt");
-
- // Synchronize the ABI Flags information with the FeatureBits information we
- // updated above.
- getTargetStreamer().updateABIInfo(*this);
-
- // If printing assembly, use the recently updated ABI Flags information.
- // If generating ELF, don't do anything (the .MIPS.abiflags section gets
- // emitted later).
- getTargetStreamer().emitDirectiveModuleMT();
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- return false; // parseDirectiveModule has finished successfully.
- } else if (Option == "crc") {
- setModuleFeatureBits(Mips::FeatureCRC, "crc");
-
- // Synchronize the ABI Flags information with the FeatureBits information we
- // updated above.
- getTargetStreamer().updateABIInfo(*this);
-
- // If printing assembly, use the recently updated ABI Flags information.
- // If generating ELF, don't do anything (the .MIPS.abiflags section gets
- // emitted later).
- getTargetStreamer().emitDirectiveModuleCRC();
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- return false; // parseDirectiveModule has finished successfully.
- } else if (Option == "nocrc") {
- clearModuleFeatureBits(Mips::FeatureCRC, "crc");
-
- // Synchronize the ABI Flags information with the FeatureBits information we
- // updated above.
- getTargetStreamer().updateABIInfo(*this);
-
- // If printing assembly, use the recently updated ABI Flags information.
- // If generating ELF, don't do anything (the .MIPS.abiflags section gets
- // emitted later).
- getTargetStreamer().emitDirectiveModuleNoCRC();
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- return false; // parseDirectiveModule has finished successfully.
- } else if (Option == "virt") {
- setModuleFeatureBits(Mips::FeatureVirt, "virt");
-
- // Synchronize the ABI Flags information with the FeatureBits information we
- // updated above.
- getTargetStreamer().updateABIInfo(*this);
-
- // If printing assembly, use the recently updated ABI Flags information.
- // If generating ELF, don't do anything (the .MIPS.abiflags section gets
- // emitted later).
- getTargetStreamer().emitDirectiveModuleVirt();
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- return false; // parseDirectiveModule has finished successfully.
- } else if (Option == "novirt") {
- clearModuleFeatureBits(Mips::FeatureVirt, "virt");
-
- // Synchronize the ABI Flags information with the FeatureBits information we
- // updated above.
- getTargetStreamer().updateABIInfo(*this);
-
- // If printing assembly, use the recently updated ABI Flags information.
- // If generating ELF, don't do anything (the .MIPS.abiflags section gets
- // emitted later).
- getTargetStreamer().emitDirectiveModuleNoVirt();
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- return false; // parseDirectiveModule has finished successfully.
- } else if (Option == "ginv") {
- setModuleFeatureBits(Mips::FeatureGINV, "ginv");
-
- // Synchronize the ABI Flags information with the FeatureBits information we
- // updated above.
- getTargetStreamer().updateABIInfo(*this);
-
- // If printing assembly, use the recently updated ABI Flags information.
- // If generating ELF, don't do anything (the .MIPS.abiflags section gets
- // emitted later).
- getTargetStreamer().emitDirectiveModuleGINV();
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- return false; // parseDirectiveModule has finished successfully.
- } else if (Option == "noginv") {
- clearModuleFeatureBits(Mips::FeatureGINV, "ginv");
-
- // Synchronize the ABI Flags information with the FeatureBits information we
- // updated above.
- getTargetStreamer().updateABIInfo(*this);
-
- // If printing assembly, use the recently updated ABI Flags information.
- // If generating ELF, don't do anything (the .MIPS.abiflags section gets
- // emitted later).
- getTargetStreamer().emitDirectiveModuleNoGINV();
-
- // If this is not the end of the statement, report an error.
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token, expected end of statement");
- return false;
- }
-
- return false; // parseDirectiveModule has finished successfully.
} else {
return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
}
@@ -7878,20 +5905,15 @@ bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
}
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
- // This returns false if this function recognizes the directive
- // regardless of whether it is successfully handles or reports an
- // error. Otherwise it returns true to give the generic parser a
- // chance at recognizing it.
-
MCAsmParser &Parser = getParser();
StringRef IDVal = DirectiveID.getString();
- if (IDVal == ".cpload") {
- parseDirectiveCpLoad(DirectiveID.getLoc());
- return false;
- }
- if (IDVal == ".cprestore") {
- parseDirectiveCpRestore(DirectiveID.getLoc());
+ if (IDVal == ".cpload")
+ return parseDirectiveCpLoad(DirectiveID.getLoc());
+ if (IDVal == ".cprestore")
+ return parseDirectiveCpRestore(DirectiveID.getLoc());
+ if (IDVal == ".dword") {
+ parseDataDirective(8, DirectiveID.getLoc());
return false;
}
if (IDVal == ".ent") {
@@ -8046,8 +6068,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
}
if (IDVal == ".set") {
- parseDirectiveSet();
- return false;
+ return parseDirectiveSet();
}
if (IDVal == ".mask" || IDVal == ".fmask") {
@@ -8121,72 +6142,39 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
}
- if (IDVal == ".dtprelword") {
- parseDirectiveDtpRelWord();
- return false;
- }
-
- if (IDVal == ".dtpreldword") {
- parseDirectiveDtpRelDWord();
+ if (IDVal == ".word") {
+ parseDataDirective(4, DirectiveID.getLoc());
return false;
}
- if (IDVal == ".tprelword") {
- parseDirectiveTpRelWord();
- return false;
- }
-
- if (IDVal == ".tpreldword") {
- parseDirectiveTpRelDWord();
- return false;
- }
-
- if (IDVal == ".option") {
- parseDirectiveOption();
- return false;
- }
+ if (IDVal == ".option")
+ return parseDirectiveOption();
if (IDVal == ".abicalls") {
getTargetStreamer().emitDirectiveAbiCalls();
if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
- Error(Parser.getTok().getLoc(),
+ Error(Parser.getTok().getLoc(),
"unexpected token, expected end of statement");
+ // Clear line
+ Parser.eatToEndOfStatement();
}
return false;
}
- if (IDVal == ".cpsetup") {
- parseDirectiveCPSetup();
- return false;
- }
- if (IDVal == ".cpreturn") {
- parseDirectiveCPReturn();
- return false;
- }
- if (IDVal == ".module") {
- parseDirectiveModule();
- return false;
- }
- if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
- parseInternalDirectiveReallowModule();
- return false;
- }
- if (IDVal == ".insn") {
- parseInsnDirective();
- return false;
- }
- if (IDVal == ".rdata") {
- parseRSectionDirective(".rodata");
- return false;
- }
- if (IDVal == ".sbss") {
- parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
- return false;
- }
- if (IDVal == ".sdata") {
- parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
- return false;
- }
+ if (IDVal == ".cpsetup")
+ return parseDirectiveCPSetup();
+
+ if (IDVal == ".cpreturn")
+ return parseDirectiveCPReturn();
+
+ if (IDVal == ".module")
+ return parseDirectiveModule();
+
+ if (IDVal == ".llvm_internal_mips_reallow_module_directive")
+ return parseInternalDirectiveReallowModule();
+
+ if (IDVal == ".insn")
+ return parseInsnDirective();
return true;
}
@@ -8205,25 +6193,12 @@ bool MipsAsmParser::parseInternalDirectiveReallowModule() {
}
extern "C" void LLVMInitializeMipsAsmParser() {
- RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
- RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
- RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
- RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
+ RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
+ RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
+ RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
+ RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
}
#define GET_REGISTER_MATCHER
#define GET_MATCHER_IMPLEMENTATION
-#define GET_MNEMONIC_SPELL_CHECKER
#include "MipsGenAsmMatcher.inc"
-
-bool MipsAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
- // Find the appropriate table for this asm variant.
- const MatchEntry *Start, *End;
- switch (VariantID) {
- default: llvm_unreachable("invalid variant!");
- case 0: Start = std::begin(MatchTable0); End = std::end(MatchTable0); break;
- }
- // Search the table.
- auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
- return MnemonicRange.first != MnemonicRange.second;
-}
diff --git a/gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
index 58f9717e1cc..e5fa7556053 100644
--- a/gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
+++ b/gnu/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
@@ -11,37 +11,28 @@
//
//===----------------------------------------------------------------------===//
-#include "MipsTargetStreamer.h"
#include "InstPrinter/MipsInstPrinter.h"
-#include "MCTargetDesc/MipsABIInfo.h"
#include "MipsELFStreamer.h"
-#include "MipsMCExpr.h"
#include "MipsMCTargetDesc.h"
#include "MipsTargetObjectFile.h"
-#include "llvm/BinaryFormat/ELF.h"
+#include "MipsTargetStreamer.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
using namespace llvm;
-namespace {
-static cl::opt<bool> RoundSectionSizes(
- "mips-round-section-sizes", cl::init(false),
- cl::desc("Round section sizes up to the section alignment"), cl::Hidden);
-} // end anonymous namespace
-
MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)
: MCTargetStreamer(S), ModuleDirectiveAllowed(true) {
GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
}
void MipsTargetStreamer::emitDirectiveSetMicroMips() {}
void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {}
-void MipsTargetStreamer::setUsesMicroMips() {}
void MipsTargetStreamer::emitDirectiveSetMips16() {}
void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); }
@@ -50,14 +41,6 @@ void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); }
-void MipsTargetStreamer::emitDirectiveSetMt() {}
-void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); }
-void MipsTargetStreamer::emitDirectiveSetCRC() {}
-void MipsTargetStreamer::emitDirectiveSetNoCRC() {}
-void MipsTargetStreamer::emitDirectiveSetVirt() {}
-void MipsTargetStreamer::emitDirectiveSetNoVirt() {}
-void MipsTargetStreamer::emitDirectiveSetGINV() {}
-void MipsTargetStreamer::emitDirectiveSetNoGINV() {}
void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) {
forbidModuleDirective();
@@ -104,14 +87,11 @@ void MipsTargetStreamer::emitDirectiveSetHardFloat() {
forbidModuleDirective();
}
void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }
-void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
-bool MipsTargetStreamer::emitDirectiveCpRestore(
- int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
+void MipsTargetStreamer::emitDirectiveCpRestore(
+ SmallVector<MCInst, 3> &StoreInsts, int Offset) {
forbidModuleDirective();
- return true;
}
void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg) {
@@ -127,13 +107,6 @@ void MipsTargetStreamer::emitDirectiveModuleOddSPReg() {
}
void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {}
void MipsTargetStreamer::emitDirectiveModuleHardFloat() {}
-void MipsTargetStreamer::emitDirectiveModuleMT() {}
-void MipsTargetStreamer::emitDirectiveModuleCRC() {}
-void MipsTargetStreamer::emitDirectiveModuleNoCRC() {}
-void MipsTargetStreamer::emitDirectiveModuleVirt() {}
-void MipsTargetStreamer::emitDirectiveModuleNoVirt() {}
-void MipsTargetStreamer::emitDirectiveModuleGINV() {}
-void MipsTargetStreamer::emitDirectiveModuleNoGINV() {}
void MipsTargetStreamer::emitDirectiveSetFp(
MipsABIFlagsSection::FpABIKind Value) {
forbidModuleDirective();
@@ -143,236 +116,6 @@ void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() {
forbidModuleDirective();
}
-void MipsTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- MCInst TmpInst;
- TmpInst.setOpcode(Opcode);
- TmpInst.addOperand(MCOperand::createReg(Reg0));
- TmpInst.setLoc(IDLoc);
- getStreamer().EmitInstruction(TmpInst, *STI);
-}
-
-void MipsTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1,
- SMLoc IDLoc, const MCSubtargetInfo *STI) {
- MCInst TmpInst;
- TmpInst.setOpcode(Opcode);
- TmpInst.addOperand(MCOperand::createReg(Reg0));
- TmpInst.addOperand(Op1);
- TmpInst.setLoc(IDLoc);
- getStreamer().EmitInstruction(TmpInst, *STI);
-}
-
-void MipsTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm,
- SMLoc IDLoc, const MCSubtargetInfo *STI) {
- emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI);
-}
-
-void MipsTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
- SMLoc IDLoc, const MCSubtargetInfo *STI) {
- emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI);
-}
-
-void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2,
- SMLoc IDLoc, const MCSubtargetInfo *STI) {
- MCInst TmpInst;
- TmpInst.setOpcode(Opcode);
- TmpInst.addOperand(MCOperand::createImm(Imm1));
- TmpInst.addOperand(MCOperand::createImm(Imm2));
- TmpInst.setLoc(IDLoc);
- getStreamer().EmitInstruction(TmpInst, *STI);
-}
-
-void MipsTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,
- MCOperand Op2, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- MCInst TmpInst;
- TmpInst.setOpcode(Opcode);
- TmpInst.addOperand(MCOperand::createReg(Reg0));
- TmpInst.addOperand(MCOperand::createReg(Reg1));
- TmpInst.addOperand(Op2);
- TmpInst.setLoc(IDLoc);
- getStreamer().EmitInstruction(TmpInst, *STI);
-}
-
-void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
- unsigned Reg2, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI);
-}
-
-void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,
- int16_t Imm, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI);
-}
-
-void MipsTargetStreamer::emitRRIII(unsigned Opcode, unsigned Reg0,
- unsigned Reg1, int16_t Imm0, int16_t Imm1,
- int16_t Imm2, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- MCInst TmpInst;
- TmpInst.setOpcode(Opcode);
- TmpInst.addOperand(MCOperand::createReg(Reg0));
- TmpInst.addOperand(MCOperand::createReg(Reg1));
- TmpInst.addOperand(MCOperand::createImm(Imm0));
- TmpInst.addOperand(MCOperand::createImm(Imm1));
- TmpInst.addOperand(MCOperand::createImm(Imm2));
- TmpInst.setLoc(IDLoc);
- getStreamer().EmitInstruction(TmpInst, *STI);
-}
-
-void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg,
- unsigned TrgReg, bool Is64Bit,
- const MCSubtargetInfo *STI) {
- emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
- STI);
-}
-
-void MipsTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg,
- int16_t ShiftAmount, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- if (ShiftAmount >= 32) {
- emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI);
- return;
- }
-
- emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI);
-}
-
-void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- if (hasShortDelaySlot)
- emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI);
- else
- emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
-}
-
-void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {
- const FeatureBitset &Features = STI->getFeatureBits();
- if (Features[Mips::FeatureMicroMips])
- emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI);
- else
- emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
-}
-
-/// Emit the $gp restore operation for .cprestore.
-void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc,
- STI);
-}
-
-/// Emit a store instruction with an immediate offset.
-void MipsTargetStreamer::emitStoreWithImmOffset(
- unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset,
- function_ref<unsigned()> GetATReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- if (isInt<16>(Offset)) {
- emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI);
- return;
- }
-
- // sw $8, offset($8) => lui $at, %hi(offset)
- // add $at, $at, $8
- // sw $8, %lo(offset)($at)
-
- unsigned ATReg = GetATReg();
- if (!ATReg)
- return;
-
- unsigned LoOffset = Offset & 0x0000ffff;
- unsigned HiOffset = (Offset & 0xffff0000) >> 16;
-
- // If msb of LoOffset is 1(negative number) we must increment HiOffset
- // to account for the sign-extension of the low part.
- if (LoOffset & 0x8000)
- HiOffset++;
-
- // Generate the base address in ATReg.
- emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI);
- if (BaseReg != Mips::ZERO)
- emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
- // Emit the store with the adjusted base and offset.
- emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI);
-}
-
-/// Emit a store instruction with an symbol offset. Symbols are assumed to be
-/// out of range for a simm16 will be expanded to appropriate instructions.
-void MipsTargetStreamer::emitStoreWithSymOffset(
- unsigned Opcode, unsigned SrcReg, unsigned BaseReg, MCOperand &HiOperand,
- MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- // sw $8, sym => lui $at, %hi(sym)
- // sw $8, %lo(sym)($at)
-
- // Generate the base address in ATReg.
- emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI);
- if (BaseReg != Mips::ZERO)
- emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
- // Emit the store with the adjusted base and offset.
- emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI);
-}
-
-/// Emit a load instruction with an immediate offset. DstReg and TmpReg are
-/// permitted to be the same register iff DstReg is distinct from BaseReg and
-/// DstReg is a GPR. It is the callers responsibility to identify such cases
-/// and pass the appropriate register in TmpReg.
-void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg,
- unsigned BaseReg, int64_t Offset,
- unsigned TmpReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- if (isInt<16>(Offset)) {
- emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI);
- return;
- }
-
- // 1) lw $8, offset($9) => lui $8, %hi(offset)
- // add $8, $8, $9
- // lw $8, %lo(offset)($9)
- // 2) lw $8, offset($8) => lui $at, %hi(offset)
- // add $at, $at, $8
- // lw $8, %lo(offset)($at)
-
- unsigned LoOffset = Offset & 0x0000ffff;
- unsigned HiOffset = (Offset & 0xffff0000) >> 16;
-
- // If msb of LoOffset is 1(negative number) we must increment HiOffset
- // to account for the sign-extension of the low part.
- if (LoOffset & 0x8000)
- HiOffset++;
-
- // Generate the base address in TmpReg.
- emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI);
- if (BaseReg != Mips::ZERO)
- emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
- // Emit the load with the adjusted base and offset.
- emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI);
-}
-
-/// Emit a load instruction with an symbol offset. Symbols are assumed to be
-/// out of range for a simm16 will be expanded to appropriate instructions.
-/// DstReg and TmpReg are permitted to be the same register iff DstReg is a
-/// GPR. It is the callers responsibility to identify such cases and pass the
-/// appropriate register in TmpReg.
-void MipsTargetStreamer::emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg,
- unsigned BaseReg,
- MCOperand &HiOperand,
- MCOperand &LoOperand,
- unsigned TmpReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- // 1) lw $8, sym => lui $8, %hi(sym)
- // lw $8, %lo(sym)($8)
- // 2) ldc1 $f0, sym => lui $at, %hi(sym)
- // ldc1 $f0, %lo(sym)($at)
-
- // Generate the base address in TmpReg.
- emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
- if (BaseReg != Mips::ZERO)
- emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
- // Emit the load with the adjusted base and offset.
- emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI);
-}
-
MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,
formatted_raw_ostream &OS)
: MipsTargetStreamer(S), OS(OS) {}
@@ -427,46 +170,6 @@ void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() {
MipsTargetStreamer::emitDirectiveSetNoMsa();
}
-void MipsTargetAsmStreamer::emitDirectiveSetMt() {
- OS << "\t.set\tmt\n";
- MipsTargetStreamer::emitDirectiveSetMt();
-}
-
-void MipsTargetAsmStreamer::emitDirectiveSetNoMt() {
- OS << "\t.set\tnomt\n";
- MipsTargetStreamer::emitDirectiveSetNoMt();
-}
-
-void MipsTargetAsmStreamer::emitDirectiveSetCRC() {
- OS << "\t.set\tcrc\n";
- MipsTargetStreamer::emitDirectiveSetCRC();
-}
-
-void MipsTargetAsmStreamer::emitDirectiveSetNoCRC() {
- OS << "\t.set\tnocrc\n";
- MipsTargetStreamer::emitDirectiveSetNoCRC();
-}
-
-void MipsTargetAsmStreamer::emitDirectiveSetVirt() {
- OS << "\t.set\tvirt\n";
- MipsTargetStreamer::emitDirectiveSetVirt();
-}
-
-void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() {
- OS << "\t.set\tnovirt\n";
- MipsTargetStreamer::emitDirectiveSetNoVirt();
-}
-
-void MipsTargetAsmStreamer::emitDirectiveSetGINV() {
- OS << "\t.set\tginv\n";
- MipsTargetStreamer::emitDirectiveSetGINV();
-}
-
-void MipsTargetAsmStreamer::emitDirectiveSetNoGINV() {
- OS << "\t.set\tnoginv\n";
- MipsTargetStreamer::emitDirectiveSetNoGINV();
-}
-
void MipsTargetAsmStreamer::emitDirectiveSetAt() {
OS << "\t.set\tat\n";
MipsTargetStreamer::emitDirectiveSetAt();
@@ -609,11 +312,6 @@ void MipsTargetAsmStreamer::emitDirectiveSetDsp() {
MipsTargetStreamer::emitDirectiveSetDsp();
}
-void MipsTargetAsmStreamer::emitDirectiveSetDspr2() {
- OS << "\t.set\tdspr2\n";
- MipsTargetStreamer::emitDirectiveSetDspr2();
-}
-
void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() {
OS << "\t.set\tnodsp\n";
MipsTargetStreamer::emitDirectiveSetNoDsp();
@@ -666,12 +364,10 @@ void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) {
forbidModuleDirective();
}
-bool MipsTargetAsmStreamer::emitDirectiveCpRestore(
- int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);
+void MipsTargetAsmStreamer::emitDirectiveCpRestore(
+ SmallVector<MCInst, 3> &StoreInsts, int Offset) {
+ MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset);
OS << "\t.cprestore\t" << Offset << "\n";
- return true;
}
void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
@@ -736,48 +432,12 @@ void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() {
OS << "\t.module\thardfloat\n";
}
-void MipsTargetAsmStreamer::emitDirectiveModuleMT() {
- OS << "\t.module\tmt\n";
-}
-
-void MipsTargetAsmStreamer::emitDirectiveModuleCRC() {
- OS << "\t.module\tcrc\n";
-}
-
-void MipsTargetAsmStreamer::emitDirectiveModuleNoCRC() {
- OS << "\t.module\tnocrc\n";
-}
-
-void MipsTargetAsmStreamer::emitDirectiveModuleVirt() {
- OS << "\t.module\tvirt\n";
-}
-
-void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() {
- OS << "\t.module\tnovirt\n";
-}
-
-void MipsTargetAsmStreamer::emitDirectiveModuleGINV() {
- OS << "\t.module\tginv\n";
-}
-
-void MipsTargetAsmStreamer::emitDirectiveModuleNoGINV() {
- OS << "\t.module\tnoginv\n";
-}
-
// This part is for ELF object output.
MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
const MCSubtargetInfo &STI)
: MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) {
MCAssembler &MCA = getStreamer().getAssembler();
-
- // It's possible that MCObjectFileInfo isn't fully initialized at this point
- // due to an initialization order problem where LLVMTargetMachine creates the
- // target streamer before TargetLoweringObjectFile calls
- // InitializeMCObjectFileInfo. There doesn't seem to be a single place that
- // covers all cases so this statement covers most cases and direct object
- // emission must call setPic() once MCObjectFileInfo has been initialized. The
- // cases we don't handle here are covered by MipsAsmPrinter.
- Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent();
+ Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_;
const FeatureBitset &Features = STI.getFeatureBits();
@@ -794,17 +454,6 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
// issues as well.
unsigned EFlags = MCA.getELFHeaderEFlags();
- // FIXME: Fix a dependency issue by instantiating the ABI object to some
- // default based off the triple. The triple doesn't describe the target
- // fully, but any external user of the API that uses the MCTargetStreamer
- // would otherwise crash on assertion failure.
-
- ABI = MipsABIInfo(
- STI.getTargetTriple().getArch() == Triple::ArchType::mipsel ||
- STI.getTargetTriple().getArch() == Triple::ArchType::mips
- ? MipsABIInfo::O32()
- : MipsABIInfo::N64());
-
// Architecture
if (Features[Mips::FeatureMips64r6])
EFlags |= ELF::EF_MIPS_ARCH_64R6;
@@ -833,26 +482,27 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
else
EFlags |= ELF::EF_MIPS_ARCH_1;
- // Machine
- if (Features[Mips::FeatureCnMips])
- EFlags |= ELF::EF_MIPS_MACH_OCTEON;
-
// Other options.
if (Features[Mips::FeatureNaN2008])
EFlags |= ELF::EF_MIPS_NAN2008;
+ // -mabicalls and -mplt are not implemented but we should act as if they were
+ // given.
+ EFlags |= ELF::EF_MIPS_CPIC;
+
MCA.setELFHeaderEFlags(EFlags);
}
void MipsTargetELFStreamer::emitLabel(MCSymbol *S) {
auto *Symbol = cast<MCSymbolELF>(S);
+ if (!isMicroMipsEnabled())
+ return;
getStreamer().getAssembler().registerSymbol(*Symbol);
uint8_t Type = Symbol->getType();
if (Type != ELF::STT_FUNC)
return;
- if (isMicroMipsEnabled())
- Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
+ Symbol->setOther(ELF::STO_MIPS_MICROMIPS);
}
void MipsTargetELFStreamer::finish() {
@@ -871,26 +521,6 @@ void MipsTargetELFStreamer::finish() {
DataSection.setAlignment(std::max(16u, DataSection.getAlignment()));
BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment()));
- if (RoundSectionSizes) {
- // Make sections sizes a multiple of the alignment. This is useful for
- // verifying the output of IAS against the output of other assemblers but
- // it's not necessary to produce a correct object and increases section
- // size.
- MCStreamer &OS = getStreamer();
- for (MCSection &S : MCA) {
- MCSectionELF &Section = static_cast<MCSectionELF &>(S);
-
- unsigned Alignment = Section.getAlignment();
- if (Alignment) {
- OS.SwitchSection(&Section);
- if (Section.UseCodeAlign())
- OS.EmitCodeAlignment(Alignment, Alignment);
- else
- OS.EmitValueToAlignment(Alignment, 0, 1, Alignment);
- }
- }
- }
-
const FeatureBitset &Features = STI.getFeatureBits();
// Update e_header flags. See the FIXME and comment above in
@@ -910,13 +540,10 @@ void MipsTargetELFStreamer::finish() {
} else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64])
EFlags |= ELF::EF_MIPS_32BITMODE;
- // -mplt is not implemented but we should act as if it was
- // given.
- if (!Features[Mips::FeatureNoABICalls])
- EFlags |= ELF::EF_MIPS_CPIC;
-
- if (Pic)
- EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC;
+ // If we've set the cpic eflag and we're n64, go ahead and set the pic
+ // one as well.
+ if (EFlags & ELF::EF_MIPS_CPIC && getABI().IsN64())
+ EFlags |= ELF::EF_MIPS_PIC;
MCA.setELFHeaderEFlags(EFlags);
@@ -949,6 +576,11 @@ MCELFStreamer &MipsTargetELFStreamer::getStreamer() {
void MipsTargetELFStreamer::emitDirectiveSetMicroMips() {
MicroMipsEnabled = true;
+
+ MCAssembler &MCA = getStreamer().getAssembler();
+ unsigned Flags = MCA.getELFHeaderEFlags();
+ Flags |= ELF::EF_MIPS_MICROMIPS;
+ MCA.setELFHeaderEFlags(Flags);
forbidModuleDirective();
}
@@ -957,13 +589,6 @@ void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() {
forbidModuleDirective();
}
-void MipsTargetELFStreamer::setUsesMicroMips() {
- MCAssembler &MCA = getStreamer().getAssembler();
- unsigned Flags = MCA.getELFHeaderEFlags();
- Flags |= ELF::EF_MIPS_MICROMIPS;
- MCA.setELFHeaderEFlags(Flags);
-}
-
void MipsTargetELFStreamer::emitDirectiveSetMips16() {
MCAssembler &MCA = getStreamer().getAssembler();
unsigned Flags = MCA.getELFHeaderEFlags();
@@ -985,7 +610,8 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {
MCContext &Context = MCA.getContext();
MCStreamer &OS = getStreamer();
- MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0);
+ MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS,
+ ELF::SHF_ALLOC | ELF::SHT_REL);
MCSymbol *Sym = Context.getOrCreateSymbol(Name);
const MCSymbolRefExpr *ExprRef =
@@ -1022,10 +648,10 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {
const MCExpr *Size = MCBinaryExpr::createSub(
MCSymbolRefExpr::create(CurPCSym, MCSymbolRefExpr::VK_None, Context),
ExprRef, Context);
-
- // The ELFObjectWriter can determine the absolute size as it has access to
- // the layout information of the assembly file, so a size expression rather
- // than an absolute value is ok here.
+ int64_t AbsSize;
+ if (!Size->evaluateAsAbsolute(AbsSize, MCA))
+ llvm_unreachable("Function size must be evaluatable as absolute");
+ Size = MCConstantExpr::create(AbsSize, Context);
static_cast<MCSymbolELF *>(Sym)->setSize(Size);
}
@@ -1134,11 +760,8 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
MCInst TmpInst;
TmpInst.setOpcode(Mips::LUi);
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
- const MCExpr *HiSym = MipsMCExpr::create(
- MipsMCExpr::MEK_HI,
- MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
- MCA.getContext()),
- MCA.getContext());
+ const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::create(
+ "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext());
TmpInst.addOperand(MCOperand::createExpr(HiSym));
getStreamer().EmitInstruction(TmpInst, STI);
@@ -1147,11 +770,8 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
TmpInst.setOpcode(Mips::ADDiu);
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
- const MCExpr *LoSym = MipsMCExpr::create(
- MipsMCExpr::MEK_LO,
- MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
- MCA.getContext()),
- MCA.getContext());
+ const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::create(
+ "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext());
TmpInst.addOperand(MCOperand::createExpr(LoSym));
getStreamer().EmitInstruction(TmpInst, STI);
@@ -1166,10 +786,9 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
forbidModuleDirective();
}
-bool MipsTargetELFStreamer::emitDirectiveCpRestore(
- int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI) {
- MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);
+void MipsTargetELFStreamer::emitDirectiveCpRestore(
+ SmallVector<MCInst, 3> &StoreInsts, int Offset) {
+ MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset);
// .cprestore offset
// When PIC mode is enabled and the O32 ABI is used, this directive expands
// to:
@@ -1179,12 +798,10 @@ bool MipsTargetELFStreamer::emitDirectiveCpRestore(
// Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
// is used in non-PIC mode.
if (!Pic || (getABI().IsN32() || getABI().IsN64()))
- return true;
+ return;
- // Store the $gp on the stack.
- emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc,
- STI);
- return true;
+ for (const MCInst &Inst : StoreInsts)
+ getStreamer().EmitInstruction(Inst, STI);
}
void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
@@ -1195,55 +812,54 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
if (!Pic || !(getABI().IsN32() || getABI().IsN64()))
return;
- forbidModuleDirective();
-
MCAssembler &MCA = getStreamer().getAssembler();
MCInst Inst;
// Either store the old $gp in a register or on the stack
if (IsReg) {
// move $save, $gpreg
- emitRRR(Mips::OR64, RegOrOffset, Mips::GP, Mips::ZERO, SMLoc(), &STI);
+ Inst.setOpcode(Mips::OR64);
+ Inst.addOperand(MCOperand::createReg(RegOrOffset));
+ Inst.addOperand(MCOperand::createReg(Mips::GP));
+ Inst.addOperand(MCOperand::createReg(Mips::ZERO));
} else {
// sd $gpreg, offset($sp)
- emitRRI(Mips::SD, Mips::GP, Mips::SP, RegOrOffset, SMLoc(), &STI);
- }
-
- if (getABI().IsN32()) {
- MCSymbol *GPSym = MCA.getContext().getOrCreateSymbol("__gnu_local_gp");
- const MipsMCExpr *HiExpr = MipsMCExpr::create(
- MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(GPSym, MCA.getContext()),
- MCA.getContext());
- const MipsMCExpr *LoExpr = MipsMCExpr::create(
- MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(GPSym, MCA.getContext()),
- MCA.getContext());
-
- // lui $gp, %hi(__gnu_local_gp)
- emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
-
- // addiu $gp, $gp, %lo(__gnu_local_gp)
- emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
- SMLoc(), &STI);
-
- return;
+ Inst.setOpcode(Mips::SD);
+ Inst.addOperand(MCOperand::createReg(Mips::GP));
+ Inst.addOperand(MCOperand::createReg(Mips::SP));
+ Inst.addOperand(MCOperand::createImm(RegOrOffset));
}
+ getStreamer().EmitInstruction(Inst, STI);
+ Inst.clear();
- const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff(
- MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
- MCA.getContext());
- const MipsMCExpr *LoExpr = MipsMCExpr::createGpOff(
- MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
- MCA.getContext());
+ const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
+ &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext());
+ const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
+ &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext());
// lui $gp, %hi(%neg(%gp_rel(funcSym)))
- emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
+ Inst.setOpcode(Mips::LUi);
+ Inst.addOperand(MCOperand::createReg(Mips::GP));
+ Inst.addOperand(MCOperand::createExpr(HiExpr));
+ getStreamer().EmitInstruction(Inst, STI);
+ Inst.clear();
// addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
- emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
- SMLoc(), &STI);
+ Inst.setOpcode(Mips::ADDiu);
+ Inst.addOperand(MCOperand::createReg(Mips::GP));
+ Inst.addOperand(MCOperand::createReg(Mips::GP));
+ Inst.addOperand(MCOperand::createExpr(LoExpr));
+ getStreamer().EmitInstruction(Inst, STI);
+ Inst.clear();
// daddu $gp, $gp, $funcreg
- emitRRR(Mips::DADDu, Mips::GP, Mips::GP, RegNo, SMLoc(), &STI);
+ Inst.setOpcode(Mips::DADDu);
+ Inst.addOperand(MCOperand::createReg(Mips::GP));
+ Inst.addOperand(MCOperand::createReg(Mips::GP));
+ Inst.addOperand(MCOperand::createReg(RegNo));
+ getStreamer().EmitInstruction(Inst, STI);
+
+ forbidModuleDirective();
}
void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
diff --git a/gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td b/gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td
index 5729182deaf..6b09cfa4c73 100644
--- a/gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td
+++ b/gnu/llvm/lib/Target/Mips/Mips64InstrInfo.td
@@ -15,6 +15,19 @@
// Mips Operand, Complex Patterns and Transformations Definitions.
//===----------------------------------------------------------------------===//
+// Unsigned Operand
+def uimm16_64 : Operand<i64> {
+ let PrintMethod = "printUnsignedImm";
+}
+
+// Signed Operand
+def simm10_64 : Operand<i64>;
+
+// Transformation Function - get Imm - 32.
+def Subtract32 : SDNodeXForm<imm, [{
+ return getImm(N, (unsigned)N->getZExtValue() - 32);
+}]>;
+
// shamt must fit in 6 bits.
def immZExt6 : ImmLeaf<i32, [{return Imm == (Imm & 0x3f);}]>;
@@ -24,7 +37,7 @@ def immSExt10_64 : PatLeaf<(i64 imm),
[{ return isInt<10>(N->getSExtValue()); }]>;
def immZExt16_64 : PatLeaf<(i64 imm),
- [{ return isUInt<16>(N->getZExtValue()); }]>;
+ [{ return isInt<16>(N->getZExtValue()); }]>;
def immZExt5_64 : ImmLeaf<i64, [{ return Imm == (Imm & 0x1f); }]>;
@@ -58,19 +71,6 @@ def PowerOf2HI : PatLeaf<(imm), [{
return false;
}]>;
-def PowerOf2LO_i32 : PatLeaf<(imm), [{
- if (N->getValueType(0) == MVT::i32) {
- uint64_t Imm = N->getZExtValue();
- return isPowerOf2_32(Imm) && isUInt<32>(Imm);
- }
- else
- return false;
-}]>;
-
-def assertzext_lt_i32 : PatFrag<(ops node:$src), (assertzext node:$src), [{
- return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLT(MVT::i32);
-}]>;
-
//===----------------------------------------------------------------------===//
// Instructions specific format
//===----------------------------------------------------------------------===//
@@ -85,19 +85,8 @@ let usesCustomInserter = 1 in {
def ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap<atomic_cmp_swap_64, GPR64>;
}
-def ATOMIC_LOAD_ADD_I64_POSTRA : Atomic2OpsPostRA<GPR64>;
-def ATOMIC_LOAD_SUB_I64_POSTRA : Atomic2OpsPostRA<GPR64>;
-def ATOMIC_LOAD_AND_I64_POSTRA : Atomic2OpsPostRA<GPR64>;
-def ATOMIC_LOAD_OR_I64_POSTRA : Atomic2OpsPostRA<GPR64>;
-def ATOMIC_LOAD_XOR_I64_POSTRA : Atomic2OpsPostRA<GPR64>;
-def ATOMIC_LOAD_NAND_I64_POSTRA : Atomic2OpsPostRA<GPR64>;
-
-def ATOMIC_SWAP_I64_POSTRA : Atomic2OpsPostRA<GPR64>;
-
-def ATOMIC_CMP_SWAP_I64_POSTRA : AtomicCmpSwapPostRA<GPR64>;
-
/// Pseudo instructions for loading and storing accumulator registers.
-let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in {
+let isPseudo = 1, isCodeGenOnly = 1 in {
def LOAD_ACC128 : Load<"", ACC128>;
def STORE_ACC128 : Store<"", ACC128>;
}
@@ -107,122 +96,97 @@ let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in {
//===----------------------------------------------------------------------===//
let DecoderNamespace = "Mips64" in {
/// Arithmetic Instructions (ALU Immediate)
-def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd, II_DADDI>,
- ADDI_FM<0x18>, ISA_MIPS3_NOT_32R6_64R6;
-let AdditionalPredicates = [NotInMicroMips] in {
- def DADDiu : ArithLogicI<"daddiu", simm16_64, GPR64Opnd, II_DADDIU,
- immSExt16, add>,
- ADDI_FM<0x19>, IsAsCheapAsAMove, ISA_MIPS3;
-}
+def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd>, ADDI_FM<0x18>,
+ ISA_MIPS3_NOT_32R6_64R6;
+def DADDiu : ArithLogicI<"daddiu", simm16_64, GPR64Opnd, II_DADDIU,
+ immSExt16, add>,
+ ADDI_FM<0x19>, IsAsCheapAsAMove, ISA_MIPS3;
let isCodeGenOnly = 1 in {
def SLTi64 : SetCC_I<"slti", setlt, simm16_64, immSExt16, GPR64Opnd>,
- SLTI_FM<0xa>, GPR_64;
+ SLTI_FM<0xa>;
def SLTiu64 : SetCC_I<"sltiu", setult, simm16_64, immSExt16, GPR64Opnd>,
- SLTI_FM<0xb>, GPR_64;
+ SLTI_FM<0xb>;
def ANDi64 : ArithLogicI<"andi", uimm16_64, GPR64Opnd, II_AND, immZExt16, and>,
- ADDI_FM<0xc>, GPR_64;
+ ADDI_FM<0xc>;
def ORi64 : ArithLogicI<"ori", uimm16_64, GPR64Opnd, II_OR, immZExt16, or>,
- ADDI_FM<0xd>, GPR_64;
+ ADDI_FM<0xd>;
def XORi64 : ArithLogicI<"xori", uimm16_64, GPR64Opnd, II_XOR, immZExt16, xor>,
- ADDI_FM<0xe>, GPR_64;
-def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64_relaxed>, LUI_FM, GPR_64;
+ ADDI_FM<0xe>;
+def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64>, LUI_FM;
}
/// Arithmetic Instructions (3-Operand, R-Type)
-let AdditionalPredicates = [NotInMicroMips] in {
- def DADD : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>, ADD_FM<0, 0x2c>,
- ISA_MIPS3;
- def DADDu : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>,
- ADD_FM<0, 0x2d>, ISA_MIPS3;
- def DSUBu : ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>,
- ADD_FM<0, 0x2f>, ISA_MIPS3;
- def DSUB : ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB>, ADD_FM<0, 0x2e>,
- ISA_MIPS3;
-}
+def DADD : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>, ADD_FM<0, 0x2c>,
+ ISA_MIPS3;
+def DADDu : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>, ADD_FM<0, 0x2d>,
+ ISA_MIPS3;
+def DSUBu : ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>, ADD_FM<0, 0x2f>,
+ ISA_MIPS3;
+def DSUB : ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB>, ADD_FM<0, 0x2e>,
+ ISA_MIPS3;
let isCodeGenOnly = 1 in {
-def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>, GPR_64;
-def SLTu64 : SetCC_R<"sltu", setult, GPR64Opnd>, ADD_FM<0, 0x2b>, GPR_64;
-def AND64 : ArithLogicR<"and", GPR64Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>,
- GPR_64;
-def OR64 : ArithLogicR<"or", GPR64Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>,
- GPR_64;
-def XOR64 : ArithLogicR<"xor", GPR64Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>,
- GPR_64;
-def NOR64 : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>, GPR_64;
+def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>;
+def SLTu64 : SetCC_R<"sltu", setult, GPR64Opnd>, ADD_FM<0, 0x2b>;
+def AND64 : ArithLogicR<"and", GPR64Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>;
+def OR64 : ArithLogicR<"or", GPR64Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>;
+def XOR64 : ArithLogicR<"xor", GPR64Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>;
+def NOR64 : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>;
}
/// Shift Instructions
-let AdditionalPredicates = [NotInMicroMips] in {
- def DSLL : shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, shl,
- immZExt6>,
+def DSLL : shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, shl, immZExt6>,
SRA_FM<0x38, 0>, ISA_MIPS3;
- def DSRL : shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, srl,
- immZExt6>,
+def DSRL : shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, srl, immZExt6>,
SRA_FM<0x3a, 0>, ISA_MIPS3;
- def DSRA : shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, sra,
- immZExt6>,
+def DSRA : shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, sra, immZExt6>,
SRA_FM<0x3b, 0>, ISA_MIPS3;
- def DSLLV : shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>,
- SRLV_FM<0x14, 0>, ISA_MIPS3;
- def DSRAV : shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>,
- SRLV_FM<0x17, 0>, ISA_MIPS3;
- def DSRLV : shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>,
- SRLV_FM<0x16, 0>, ISA_MIPS3;
- def DSLL32 : shift_rotate_imm<"dsll32", uimm5, GPR64Opnd, II_DSLL32>,
- SRA_FM<0x3c, 0>, ISA_MIPS3;
- def DSRL32 : shift_rotate_imm<"dsrl32", uimm5, GPR64Opnd, II_DSRL32>,
- SRA_FM<0x3e, 0>, ISA_MIPS3;
- def DSRA32 : shift_rotate_imm<"dsra32", uimm5, GPR64Opnd, II_DSRA32>,
- SRA_FM<0x3f, 0>, ISA_MIPS3;
+def DSLLV : shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>,
+ SRLV_FM<0x14, 0>, ISA_MIPS3;
+def DSRLV : shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>,
+ SRLV_FM<0x16, 0>, ISA_MIPS3;
+def DSRAV : shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>,
+ SRLV_FM<0x17, 0>, ISA_MIPS3;
+def DSLL32 : shift_rotate_imm<"dsll32", uimm5, GPR64Opnd, II_DSLL32>,
+ SRA_FM<0x3c, 0>, ISA_MIPS3;
+def DSRL32 : shift_rotate_imm<"dsrl32", uimm5, GPR64Opnd, II_DSRL32>,
+ SRA_FM<0x3e, 0>, ISA_MIPS3;
+def DSRA32 : shift_rotate_imm<"dsra32", uimm5, GPR64Opnd, II_DSRA32>,
+ SRA_FM<0x3f, 0>, ISA_MIPS3;
// Rotate Instructions
- def DROTR : shift_rotate_imm<"drotr", uimm6, GPR64Opnd, II_DROTR, rotr,
- immZExt6>,
- SRA_FM<0x3a, 1>, ISA_MIPS64R2;
- def DROTRV : shift_rotate_reg<"drotrv", GPR64Opnd, II_DROTRV, rotr>,
- SRLV_FM<0x16, 1>, ISA_MIPS64R2;
- def DROTR32 : shift_rotate_imm<"drotr32", uimm5, GPR64Opnd, II_DROTR32>,
- SRA_FM<0x3e, 1>, ISA_MIPS64R2;
-}
+def DROTR : shift_rotate_imm<"drotr", uimm6, GPR64Opnd, II_DROTR, rotr,
+ immZExt6>,
+ SRA_FM<0x3a, 1>, ISA_MIPS64R2;
+def DROTRV : shift_rotate_reg<"drotrv", GPR64Opnd, II_DROTRV, rotr>,
+ SRLV_FM<0x16, 1>, ISA_MIPS64R2;
+def DROTR32 : shift_rotate_imm<"drotr32", uimm5, GPR64Opnd, II_DROTR32>,
+ SRA_FM<0x3e, 1>, ISA_MIPS64R2;
/// Load and Store Instructions
/// aligned
let isCodeGenOnly = 1 in {
-def LB64 : Load<"lb", GPR64Opnd, sextloadi8, II_LB>, LW_FM<0x20>, GPR_64;
-def LBu64 : Load<"lbu", GPR64Opnd, zextloadi8, II_LBU>, LW_FM<0x24>, GPR_64;
-def LH64 : Load<"lh", GPR64Opnd, sextloadi16, II_LH>, LW_FM<0x21>, GPR_64;
-def LHu64 : Load<"lhu", GPR64Opnd, zextloadi16, II_LHU>, LW_FM<0x25>, GPR_64;
-def LW64 : Load<"lw", GPR64Opnd, sextloadi32, II_LW>, LW_FM<0x23>, GPR_64;
-def SB64 : Store<"sb", GPR64Opnd, truncstorei8, II_SB>, LW_FM<0x28>, GPR_64;
-def SH64 : Store<"sh", GPR64Opnd, truncstorei16, II_SH>, LW_FM<0x29>,
- GPR_64;
-def SW64 : Store<"sw", GPR64Opnd, truncstorei32, II_SW>, LW_FM<0x2b>,
- GPR_64;
-}
-
-let AdditionalPredicates = [NotInMicroMips] in {
- def LWu : MMRel, Load<"lwu", GPR64Opnd, zextloadi32, II_LWU>,
- LW_FM<0x27>, ISA_MIPS3;
- def LD : LoadMemory<"ld", GPR64Opnd, mem_simmptr, load, II_LD>,
- LW_FM<0x37>, ISA_MIPS3;
- def SD : StoreMemory<"sd", GPR64Opnd, mem_simmptr, store, II_SD>,
- LW_FM<0x3f>, ISA_MIPS3;
+def LB64 : Load<"lb", GPR64Opnd, sextloadi8, II_LB>, LW_FM<0x20>;
+def LBu64 : Load<"lbu", GPR64Opnd, zextloadi8, II_LBU>, LW_FM<0x24>;
+def LH64 : Load<"lh", GPR64Opnd, sextloadi16, II_LH>, LW_FM<0x21>;
+def LHu64 : Load<"lhu", GPR64Opnd, zextloadi16, II_LHU>, LW_FM<0x25>;
+def LW64 : Load<"lw", GPR64Opnd, sextloadi32, II_LW>, LW_FM<0x23>;
+def SB64 : Store<"sb", GPR64Opnd, truncstorei8, II_SB>, LW_FM<0x28>;
+def SH64 : Store<"sh", GPR64Opnd, truncstorei16, II_SH>, LW_FM<0x29>;
+def SW64 : Store<"sw", GPR64Opnd, truncstorei32, II_SW>, LW_FM<0x2b>;
}
-
+def LWu : Load<"lwu", GPR64Opnd, zextloadi32, II_LWU>, LW_FM<0x27>, ISA_MIPS3;
+def LD : Load<"ld", GPR64Opnd, load, II_LD>, LW_FM<0x37>, ISA_MIPS3;
+def SD : Store<"sd", GPR64Opnd, store, II_SD>, LW_FM<0x3f>, ISA_MIPS3;
/// load/store left/right
let isCodeGenOnly = 1 in {
-def LWL64 : LoadLeftRight<"lwl", MipsLWL, GPR64Opnd, II_LWL>, LW_FM<0x22>,
- GPR_64;
-def LWR64 : LoadLeftRight<"lwr", MipsLWR, GPR64Opnd, II_LWR>, LW_FM<0x26>,
- GPR_64;
-def SWL64 : StoreLeftRight<"swl", MipsSWL, GPR64Opnd, II_SWL>, LW_FM<0x2a>,
- GPR_64;
-def SWR64 : StoreLeftRight<"swr", MipsSWR, GPR64Opnd, II_SWR>, LW_FM<0x2e>,
- GPR_64;
+def LWL64 : LoadLeftRight<"lwl", MipsLWL, GPR64Opnd, II_LWL>, LW_FM<0x22>;
+def LWR64 : LoadLeftRight<"lwr", MipsLWR, GPR64Opnd, II_LWR>, LW_FM<0x26>;
+def SWL64 : StoreLeftRight<"swl", MipsSWL, GPR64Opnd, II_SWL>, LW_FM<0x2a>;
+def SWR64 : StoreLeftRight<"swr", MipsSWR, GPR64Opnd, II_SWR>, LW_FM<0x2e>;
}
def LDL : LoadLeftRight<"ldl", MipsLDL, GPR64Opnd, II_LDL>, LW_FM<0x1a>,
@@ -235,81 +199,39 @@ def SDR : StoreLeftRight<"sdr", MipsSDR, GPR64Opnd, II_SDR>, LW_FM<0x2d>,
ISA_MIPS3_NOT_32R6_64R6;
/// Load-linked, Store-conditional
-let AdditionalPredicates = [NotInMicroMips] in {
- def LLD : LLBase<"lld", GPR64Opnd, mem_simmptr>, LW_FM<0x34>,
- ISA_MIPS3_NOT_32R6_64R6;
-}
+def LLD : LLBase<"lld", GPR64Opnd>, LW_FM<0x34>, ISA_MIPS3_NOT_32R6_64R6;
def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3_NOT_32R6_64R6;
-let AdditionalPredicates = [NotInMicroMips],
- DecoderNamespace = "Mips32_64_PTR64" in {
-def LL64 : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_64,
- ISA_MIPS2_NOT_32R6_64R6;
-def SC64 : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_64,
- ISA_MIPS2_NOT_32R6_64R6;
-def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>, PTR_64;
-}
-
-def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM;
-
/// Jump and Branch Instructions
let isCodeGenOnly = 1 in {
- def BEQ64 : CBranch<"beq", brtarget, seteq, GPR64Opnd>, BEQ_FM<4>,
- GPR_64;
- def BNE64 : CBranch<"bne", brtarget, setne, GPR64Opnd>, BEQ_FM<5>,
- GPR_64;
- def BGEZ64 : CBranchZero<"bgez", brtarget, setge, GPR64Opnd>, BGEZ_FM<1, 1>,
- GPR_64;
- def BGTZ64 : CBranchZero<"bgtz", brtarget, setgt, GPR64Opnd>, BGEZ_FM<7, 0>,
- GPR_64;
- def BLEZ64 : CBranchZero<"blez", brtarget, setle, GPR64Opnd>, BGEZ_FM<6, 0>,
- GPR_64;
- def BLTZ64 : CBranchZero<"bltz", brtarget, setlt, GPR64Opnd>, BGEZ_FM<1, 0>,
- GPR_64;
- let AdditionalPredicates = [NoIndirectJumpGuards] in
- def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>;
-}
-let AdditionalPredicates = [NotInMicroMips],
- DecoderNamespace = "Mips64" in {
- def JR_HB64 : JR_HB_DESC<GPR64Opnd>, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6;
- def JALR_HB64 : JALR_HB_DESC<GPR64Opnd>, JALR_HB_ENC, ISA_MIPS32R2;
-}
-def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>;
-
-let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
- NoIndirectJumpGuards] in {
- def TAILCALLREG64 : TailCallReg<JR64, GPR64Opnd>, ISA_MIPS3_NOT_32R6_64R6,
- PTR_64;
- def PseudoIndirectBranch64 : PseudoIndirectBranchBase<JR64, GPR64Opnd>,
- ISA_MIPS3_NOT_32R6_64R6;
+ def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>;
+ def BEQ64 : CBranch<"beq", brtarget, seteq, GPR64Opnd>, BEQ_FM<4>;
+ def BNE64 : CBranch<"bne", brtarget, setne, GPR64Opnd>, BEQ_FM<5>;
+ def BGEZ64 : CBranchZero<"bgez", brtarget, setge, GPR64Opnd>, BGEZ_FM<1, 1>;
+ def BGTZ64 : CBranchZero<"bgtz", brtarget, setgt, GPR64Opnd>, BGEZ_FM<7, 0>;
+ def BLEZ64 : CBranchZero<"blez", brtarget, setle, GPR64Opnd>, BGEZ_FM<6, 0>;
+ def BLTZ64 : CBranchZero<"bltz", brtarget, setlt, GPR64Opnd>, BGEZ_FM<1, 0>;
+ def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM;
+ def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>;
+ def TAILCALL64_R : TailCallReg<GPR64Opnd, JR, GPR32Opnd>;
}
-let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
- UseIndirectJumpsHazard] in {
- def TAILCALLREGHB64 : TailCallReg<JR_HB64, GPR64Opnd>,
- ISA_MIPS32R2_NOT_32R6_64R6, PTR_64;
- def PseudoIndirectHazardBranch64 : PseudoIndirectBranchBase<JR_HB64,
- GPR64Opnd>,
- ISA_MIPS32R2_NOT_32R6_64R6;
-}
+def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>;
+def PseudoIndirectBranch64 : PseudoIndirectBranchBase<GPR64Opnd>;
/// Multiply and Divide Instructions.
-let AdditionalPredicates = [NotInMicroMips] in {
- def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1c>, ISA_MIPS3_NOT_32R6_64R6;
- def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1d>, ISA_MIPS3_NOT_32R6_64R6;
-}
+def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>,
+ MULT_FM<0, 0x1c>, ISA_MIPS3_NOT_32R6_64R6;
+def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>,
+ MULT_FM<0, 0x1d>, ISA_MIPS3_NOT_32R6_64R6;
def PseudoDMULT : MultDivPseudo<DMULT, ACC128, GPR64Opnd, MipsMult,
II_DMULT>, ISA_MIPS3_NOT_32R6_64R6;
def PseudoDMULTu : MultDivPseudo<DMULTu, ACC128, GPR64Opnd, MipsMultu,
II_DMULTU>, ISA_MIPS3_NOT_32R6_64R6;
-let AdditionalPredicates = [NotInMicroMips] in {
- def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1e>, ISA_MIPS3_NOT_32R6_64R6;
- def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1f>, ISA_MIPS3_NOT_32R6_64R6;
-}
+def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>,
+ MULT_FM<0, 0x1e>, ISA_MIPS3_NOT_32R6_64R6;
+def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>,
+ MULT_FM<0, 0x1f>, ISA_MIPS3_NOT_32R6_64R6;
def PseudoDSDIV : MultDivPseudo<DSDIV, ACC128, GPR64Opnd, MipsDivRem,
II_DDIV, 0, 1, 1>, ISA_MIPS3_NOT_32R6_64R6;
def PseudoDUDIV : MultDivPseudo<DUDIV, ACC128, GPR64Opnd, MipsDivRemU,
@@ -338,101 +260,57 @@ def SEH64 : SignExtInReg<"seh", i16, GPR64Opnd, II_SEH>, SEB_FM<0x18, 0x20>,
}
/// Count Leading
-let AdditionalPredicates = [NotInMicroMips] in {
- def DCLZ : CountLeading0<"dclz", GPR64Opnd, II_DCLZ>, CLO_FM<0x24>,
- ISA_MIPS64_NOT_64R6;
- def DCLO : CountLeading1<"dclo", GPR64Opnd, II_DCLO>, CLO_FM<0x25>,
- ISA_MIPS64_NOT_64R6;
+def DCLZ : CountLeading0<"dclz", GPR64Opnd>, CLO_FM<0x24>, ISA_MIPS64_NOT_64R6;
+def DCLO : CountLeading1<"dclo", GPR64Opnd>, CLO_FM<0x25>, ISA_MIPS64_NOT_64R6;
/// Double Word Swap Bytes/HalfWords
- def DSBH : SubwordSwap<"dsbh", GPR64Opnd, II_DSBH>, SEB_FM<2, 0x24>,
- ISA_MIPS64R2;
- def DSHD : SubwordSwap<"dshd", GPR64Opnd, II_DSHD>, SEB_FM<5, 0x24>,
- ISA_MIPS64R2;
+def DSBH : SubwordSwap<"dsbh", GPR64Opnd>, SEB_FM<2, 0x24>, ISA_MIPS64R2;
+def DSHD : SubwordSwap<"dshd", GPR64Opnd>, SEB_FM<5, 0x24>, ISA_MIPS64R2;
- def LEA_ADDiu64 : EffectiveAddress<"daddiu", GPR64Opnd>, LW_FM<0x19>,
- GPR_64;
-}
+def LEA_ADDiu64 : EffectiveAddress<"daddiu", GPR64Opnd>, LW_FM<0x19>;
let isCodeGenOnly = 1 in
-def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM, GPR_64;
+def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM;
let AdditionalPredicates = [NotInMicroMips] in {
- // The 'pos + size' constraints for code generation are enforced by the
- // code that lowers into MipsISD::Ext.
- // For assembly parsing, we alias dextu and dextm to dext, and match by
- // operand were possible then check the 'pos + size' in MipsAsmParser.
- // We override the generated decoder to enforce that dext always comes out
- // for dextm and dextu like binutils.
- let DecoderMethod = "DecodeDEXT" in {
- def DEXT : ExtBase<"dext", GPR64Opnd, uimm5_report_uimm6,
- uimm5_plus1_report_uimm6, immZExt5, immZExt5Plus1,
- MipsExt>, EXT_FM<3>, ISA_MIPS64R2;
- def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, immZExt5,
- immZExt5Plus33, MipsExt>, EXT_FM<1>, ISA_MIPS64R2;
- def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1,
- immZExt5Plus32, immZExt5Plus1, MipsExt>, EXT_FM<2>,
- ISA_MIPS64R2;
- }
- // The 'pos + size' constraints for code generation are enforced by the
- // code that lowers into MipsISD::Ins.
- // For assembly parsing, we alias dinsu and dinsm to dins, and match by
- // operand were possible then check the 'pos + size' in MipsAsmParser.
- // We override the generated decoder to enforce that dins always comes out
- // for dinsm and dinsu like binutils.
- let DecoderMethod = "DecodeDINS" in {
- def DINS : InsBase<"dins", GPR64Opnd, uimm6, uimm5_inssize_plus1,
- immZExt5, immZExt5Plus1>, EXT_FM<7>,
- ISA_MIPS64R2;
- def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, uimm5_inssize_plus1,
- immZExt5Plus32, immZExt5Plus1>,
- EXT_FM<6>, ISA_MIPS64R2;
- def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64,
- immZExt5, immZExtRange2To64>,
- EXT_FM<5>, ISA_MIPS64R2;
- }
+ // TODO: Add 'pos + size' constraint check to dext* instructions
+ // DEXT: 0 < pos + size <= 63
+ // DEXTM, DEXTU: 32 < pos + size <= 64
+ def DEXT : ExtBase<"dext", GPR64Opnd, uimm5, uimm5_plus1, MipsExt>,
+ EXT_FM<3>;
+ def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, MipsExt>,
+ EXT_FM<1>;
+ def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1,
+ MipsExt>, EXT_FM<2>;
}
-let isCodeGenOnly = 1, AdditionalPredicates = [NotInMicroMips] in {
- def DEXT64_32 : InstSE<(outs GPR64Opnd:$rt),
- (ins GPR32Opnd:$rs, uimm5_report_uimm6:$pos,
- uimm5_plus1:$size),
- "dext $rt, $rs, $pos, $size", [], II_EXT, FrmR, "dext">,
- EXT_FM<3>, ISA_MIPS64R2;
-}
+def DINS : InsBase<"dins", GPR64Opnd, uimm6, MipsIns>, EXT_FM<7>;
+def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32>, EXT_FM<6>;
+def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5>, EXT_FM<5>;
let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
def DSLL64_32 : FR<0x00, 0x3c, (outs GPR64:$rd), (ins GPR32:$rt),
- "dsll\t$rd, $rt, 32", [], II_DSLL>, GPR_64;
- let isMoveReg = 1 in {
- def SLL64_32 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR32:$rt),
- "sll\t$rd, $rt, 0", [], II_SLL>, GPR_64;
- def SLL64_64 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR64:$rt),
- "sll\t$rd, $rt, 0", [], II_SLL>, GPR_64;
- }
+ "dsll\t$rd, $rt, 32", [], II_DSLL>;
+ def SLL64_32 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR32:$rt),
+ "sll\t$rd, $rt, 0", [], II_SLL>;
+ def SLL64_64 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR64:$rt),
+ "sll\t$rd, $rt, 0", [], II_SLL>;
}
// We need the following pseudo instruction to avoid offset calculation for
// long branches. See the comment in file MipsLongBranch.cpp for detailed
// explanation.
-// Expands to: lui $dst, %highest/%higher/%hi/%lo($tgt)
-def LONG_BRANCH_LUi2Op_64 : PseudoSE<(outs GPR64Opnd:$dst),
- (ins brtarget:$tgt), []>, GPR_64;
-// Expands to: addiu $dst, %highest/%higher/%hi/%lo($tgt)
-def LONG_BRANCH_DADDiu2Op : PseudoSE<(outs GPR64Opnd:$dst),
- (ins GPR64Opnd:$src, brtarget:$tgt), []>, GPR_64;
-
// Expands to: daddiu $dst, $src, %PART($tgt - $baltgt)
// where %PART may be %hi or %lo, depending on the relocation kind
// that $tgt is annotated with.
def LONG_BRANCH_DADDiu : PseudoSE<(outs GPR64Opnd:$dst),
- (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>, GPR_64;
+ (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>;
// Cavium Octeon cnMIPS instructions
let DecoderNamespace = "CnMips",
- // FIXME: The lack of HasStdEnc is probably a bug
- EncodingPredicates = []<Predicate> in {
+ EncodingPredicates = []<Predicate>, // FIXME: The lack of HasStdEnc is probably a bug
+ AdditionalPredicates = [HasCnMips] in {
class Count1s<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
@@ -440,12 +318,11 @@ class Count1s<string opstr, RegisterOperand RO>:
let TwoOperandAliasConstraint = "$rd = $rs";
}
-class ExtsCins<string opstr, InstrItinClass itin, RegisterOperand RO,
- PatFrag PosImm, SDPatternOperator Op = null_frag>:
- InstSE<(outs RO:$rt), (ins RO:$rs, uimm5:$pos, uimm5:$lenm1),
- !strconcat(opstr, "\t$rt, $rs, $pos, $lenm1"),
- [(set RO:$rt, (Op RO:$rs, PosImm:$pos, imm:$lenm1))],
- itin, FrmR, opstr> {
+class ExtsCins<string opstr, SDPatternOperator Op = null_frag>:
+ InstSE<(outs GPR64Opnd:$rt), (ins GPR64Opnd:$rs, uimm5:$pos, uimm5:$lenm1),
+ !strconcat(opstr, " $rt, $rs, $pos, $lenm1"),
+ [(set GPR64Opnd:$rt, (Op GPR64Opnd:$rs, imm:$pos, imm:$lenm1))],
+ NoItinerary, FrmR, opstr> {
let TwoOperandAliasConstraint = "$rt = $rs";
}
@@ -479,444 +356,250 @@ class CBranchBitNum<string opstr, DAGOperand opnd, PatFrag cond_op,
let Defs = [AT];
}
-class MFC2OP<string asmstr, RegisterOperand RO, InstrItinClass itin> :
+class MFC2OP<string asmstr, RegisterOperand RO> :
InstSE<(outs RO:$rt, uimm16:$imm16), (ins),
- !strconcat(asmstr, "\t$rt, $imm16"), [], itin, FrmFR>;
+ !strconcat(asmstr, "\t$rt, $imm16"), [], NoItinerary, FrmFR>;
// Unsigned Byte Add
+let Pattern = [(set GPR64Opnd:$rd,
+ (and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))] in
def BADDu : ArithLogicR<"baddu", GPR64Opnd, 1, II_BADDU>,
- ADD_FM<0x1c, 0x28>, ASE_CNMIPS {
- let Pattern = [(set GPR64Opnd:$rd,
- (and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))];
-}
+ ADD_FM<0x1c, 0x28>;
// Branch on Bit Clear /+32
def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd,
- uimm5_64_report_uimm6>, BBIT_FM<0x32>, ASE_CNMIPS;
+ uimm5_64_report_uimm6>, BBIT_FM<0x32>;
def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, uimm5_64,
- 0x100000000>, BBIT_FM<0x36>, ASE_CNMIPS;
+ 0x100000000>,
+ BBIT_FM<0x36>;
// Branch on Bit Set /+32
def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd,
- uimm5_64_report_uimm6>, BBIT_FM<0x3a>, ASE_CNMIPS;
+ uimm5_64_report_uimm6>, BBIT_FM<0x3a>;
def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, uimm5_64,
- 0x100000000>, BBIT_FM<0x3e>, ASE_CNMIPS;
+ 0x100000000>, BBIT_FM<0x3e>;
// Multiply Doubleword to GPR
+let Defs = [HI0, LO0, P0, P1, P2] in
def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>,
- ADD_FM<0x1c, 0x03>, ASE_CNMIPS {
- let Defs = [HI0, LO0, P0, P1, P2];
-}
+ ADD_FM<0x1c, 0x03>;
-let AdditionalPredicates = [NotInMicroMips] in {
- // Extract a signed bit field /+32
- def EXTS : ExtsCins<"exts", II_EXT, GPR64Opnd, immZExt5>, EXTS_FM<0x3a>,
- ASE_MIPS64_CNMIPS;
- def EXTS32: ExtsCins<"exts32", II_EXT, GPR64Opnd, immZExt5Plus32>,
- EXTS_FM<0x3b>, ASE_MIPS64_CNMIPS;
-
- // Clear and insert a bit field /+32
- def CINS : ExtsCins<"cins", II_INS, GPR64Opnd, immZExt5, MipsCIns>,
- EXTS_FM<0x32>, ASE_MIPS64_CNMIPS;
- def CINS32: ExtsCins<"cins32", II_INS, GPR64Opnd, immZExt5Plus32, MipsCIns>,
- EXTS_FM<0x33>, ASE_MIPS64_CNMIPS;
- let isCodeGenOnly = 1 in {
- def CINS_i32 : ExtsCins<"cins", II_INS, GPR32Opnd, immZExt5, MipsCIns>,
- EXTS_FM<0x32>, ASE_MIPS64_CNMIPS;
- def CINS64_32 :InstSE<(outs GPR64Opnd:$rt),
- (ins GPR32Opnd:$rs, uimm5:$pos, uimm5:$lenm1),
- "cins\t$rt, $rs, $pos, $lenm1", [], II_INS, FrmR,
- "cins">,
- EXTS_FM<0x32>, ASE_MIPS64_CNMIPS;
- }
-}
+// Extract a signed bit field /+32
+def EXTS : ExtsCins<"exts">, EXTS_FM<0x3a>;
+def EXTS32: ExtsCins<"exts32">, EXTS_FM<0x3b>;
+
+// Clear and insert a bit field /+32
+def CINS : ExtsCins<"cins">, EXTS_FM<0x32>;
+def CINS32: ExtsCins<"cins32">, EXTS_FM<0x33>;
// Move to multiplier/product register
-def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>,
- ASE_CNMIPS;
-def MTM1 : MoveToLOHI<"mtm1", GPR64Opnd, [MPL1, P0, P1, P2]>, MTMR_FM<0x0c>,
- ASE_CNMIPS;
-def MTM2 : MoveToLOHI<"mtm2", GPR64Opnd, [MPL2, P0, P1, P2]>, MTMR_FM<0x0d>,
- ASE_CNMIPS;
-def MTP0 : MoveToLOHI<"mtp0", GPR64Opnd, [P0]>, MTMR_FM<0x09>, ASE_CNMIPS;
-def MTP1 : MoveToLOHI<"mtp1", GPR64Opnd, [P1]>, MTMR_FM<0x0a>, ASE_CNMIPS;
-def MTP2 : MoveToLOHI<"mtp2", GPR64Opnd, [P2]>, MTMR_FM<0x0b>, ASE_CNMIPS;
+def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>;
+def MTM1 : MoveToLOHI<"mtm1", GPR64Opnd, [MPL1, P0, P1, P2]>, MTMR_FM<0x0c>;
+def MTM2 : MoveToLOHI<"mtm2", GPR64Opnd, [MPL2, P0, P1, P2]>, MTMR_FM<0x0d>;
+def MTP0 : MoveToLOHI<"mtp0", GPR64Opnd, [P0]>, MTMR_FM<0x09>;
+def MTP1 : MoveToLOHI<"mtp1", GPR64Opnd, [P1]>, MTMR_FM<0x0a>;
+def MTP2 : MoveToLOHI<"mtp2", GPR64Opnd, [P2]>, MTMR_FM<0x0b>;
// Count Ones in a Word/Doubleword
-def POP : Count1s<"pop", GPR32Opnd>, POP_FM<0x2c>, ASE_CNMIPS;
-def DPOP : Count1s<"dpop", GPR64Opnd>, POP_FM<0x2d>, ASE_CNMIPS;
+def POP : Count1s<"pop", GPR32Opnd>, POP_FM<0x2c>;
+def DPOP : Count1s<"dpop", GPR64Opnd>, POP_FM<0x2d>;
// Set on equal/not equal
-def SEQ : SetCC64_R<"seq", seteq>, SEQ_FM<0x2a>, ASE_CNMIPS;
-def SEQi : SetCC64_I<"seqi", seteq>, SEQI_FM<0x2e>, ASE_CNMIPS;
-def SNE : SetCC64_R<"sne", setne>, SEQ_FM<0x2b>, ASE_CNMIPS;
-def SNEi : SetCC64_I<"snei", setne>, SEQI_FM<0x2f>, ASE_CNMIPS;
+def SEQ : SetCC64_R<"seq", seteq>, SEQ_FM<0x2a>;
+def SEQi : SetCC64_I<"seqi", seteq>, SEQI_FM<0x2e>;
+def SNE : SetCC64_R<"sne", setne>, SEQ_FM<0x2b>;
+def SNEi : SetCC64_I<"snei", setne>, SEQI_FM<0x2f>;
// 192-bit x 64-bit Unsigned Multiply and Add
-def V3MULU: ArithLogicR<"v3mulu", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x11>,
- ASE_CNMIPS {
- let Defs = [P0, P1, P2];
-}
+let Defs = [P0, P1, P2] in
+def V3MULU: ArithLogicR<"v3mulu", GPR64Opnd, 0, II_DMUL>,
+ ADD_FM<0x1c, 0x11>;
// 64-bit Unsigned Multiply and Add Move
-def VMM0 : ArithLogicR<"vmm0", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x10>,
- ASE_CNMIPS {
- let Defs = [MPL0, P0, P1, P2];
-}
+let Defs = [MPL0, P0, P1, P2] in
+def VMM0 : ArithLogicR<"vmm0", GPR64Opnd, 0, II_DMUL>,
+ ADD_FM<0x1c, 0x10>;
// 64-bit Unsigned Multiply and Add
-def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x0f>,
- ASE_CNMIPS {
- let Defs = [MPL1, MPL2, P0, P1, P2];
-}
+let Defs = [MPL1, MPL2, P0, P1, P2] in
+def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>,
+ ADD_FM<0x1c, 0x0f>;
// Move between CPU and coprocessor registers
-def DMFC2_OCTEON : MFC2OP<"dmfc2", GPR64Opnd, II_DMFC2>, MFC2OP_FM<0x12, 1>,
- ASE_CNMIPS;
-def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd, II_DMTC2>, MFC2OP_FM<0x12, 5>,
- ASE_CNMIPS;
+def DMFC2_OCTEON : MFC2OP<"dmfc2", GPR64Opnd>, MFC2OP_FM<0x12, 1>;
+def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd>, MFC2OP_FM<0x12, 5>;
}
}
/// Move between CPU and coprocessor registers
let DecoderNamespace = "Mips64", Predicates = [HasMips64] in {
-def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd, II_DMFC0>,
- MFC3OP_FM<0x10, 1, 0>, ISA_MIPS3;
-def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd, II_DMTC0>,
- MFC3OP_FM<0x10, 5, 0>, ISA_MIPS3;
-def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd, II_DMFC2>,
- MFC3OP_FM<0x12, 1, 0>, ISA_MIPS3;
-def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd, II_DMTC2>,
- MFC3OP_FM<0x12, 5, 0>, ISA_MIPS3;
+def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd>, MFC3OP_FM<0x10, 1>, ISA_MIPS3;
+def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd>, MFC3OP_FM<0x10, 5>, ISA_MIPS3;
+def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd>, MFC3OP_FM<0x12, 1>, ISA_MIPS3;
+def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd>, MFC3OP_FM<0x12, 5>, ISA_MIPS3;
}
-/// Move between CPU and guest coprocessor registers (Virtualization ASE)
-let DecoderNamespace = "Mips64" in {
- def DMFGC0 : MFC3OP<"dmfgc0", GPR64Opnd, COP0Opnd, II_DMFGC0>,
- MFC3OP_FM<0x10, 3, 1>, ISA_MIPS64R5, ASE_VIRT;
- def DMTGC0 : MTC3OP<"dmtgc0", COP0Opnd, GPR64Opnd, II_DMTGC0>,
- MFC3OP_FM<0x10, 3, 3>, ISA_MIPS64R5, ASE_VIRT;
-}
-
-let AdditionalPredicates = [UseIndirectJumpsHazard] in
- def JALRHB64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR_HB64, RA_64>;
-
//===----------------------------------------------------------------------===//
// Arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
-// Materialize i64 constants.
-defm : MaterializeImms<i64, ZERO_64, DADDiu, LUi64, ORi64>, ISA_MIPS3, GPR_64;
-
-def : MipsPat<(i64 immZExt32Low16Zero:$imm),
- (DSLL (ORi64 ZERO_64, (HI16 imm:$imm)), 16)>, ISA_MIPS3, GPR_64;
-
-def : MipsPat<(i64 immZExt32:$imm),
- (ORi64 (DSLL (ORi64 ZERO_64, (HI16 imm:$imm)), 16),
- (LO16 imm:$imm))>, ISA_MIPS3, GPR_64;
-
// extended loads
-def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>, ISA_MIPS3,
- GPR_64;
-def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>, ISA_MIPS3,
- GPR_64;
-def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>, ISA_MIPS3,
- GPR_64;
-def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>, ISA_MIPS3,
- GPR_64;
+def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>;
+def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>;
+def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>;
+def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>;
// hi/lo relocs
-let AdditionalPredicates = [NotInMicroMips] in
-defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, ISA_MIPS3, GPR_64,
- SYM_32;
-
-def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>, ISA_MIPS3,
- GPR_64;
-def : MipsPat<(MipsGotHi texternalsym:$in), (LUi64 texternalsym:$in)>,
- ISA_MIPS3, GPR_64;
-
-def : MipsPat<(MipsTlsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>,
- ISA_MIPS3, GPR_64;
-
-// highest/higher/hi/lo relocs
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsPat<(MipsJmpLink (i64 texternalsym:$dst)),
- (JAL texternalsym:$dst)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(MipsHighest (i64 tglobaladdr:$in)),
- (LUi64 tglobaladdr:$in)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(MipsHighest (i64 tblockaddress:$in)),
- (LUi64 tblockaddress:$in)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(MipsHighest (i64 tjumptable:$in)),
- (LUi64 tjumptable:$in)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(MipsHighest (i64 tconstpool:$in)),
- (LUi64 tconstpool:$in)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(MipsHighest (i64 texternalsym:$in)),
- (LUi64 texternalsym:$in)>, ISA_MIPS3, GPR_64, SYM_64;
-
- def : MipsPat<(MipsHigher (i64 tglobaladdr:$in)),
- (DADDiu ZERO_64, tglobaladdr:$in)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(MipsHigher (i64 tblockaddress:$in)),
- (DADDiu ZERO_64, tblockaddress:$in)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(MipsHigher (i64 tjumptable:$in)),
- (DADDiu ZERO_64, tjumptable:$in)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(MipsHigher (i64 tconstpool:$in)),
- (DADDiu ZERO_64, tconstpool:$in)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(MipsHigher (i64 texternalsym:$in)),
- (DADDiu ZERO_64, texternalsym:$in)>, ISA_MIPS3, GPR_64, SYM_64;
-
- def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaladdr:$lo))),
- (DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tblockaddress:$lo))),
- (DADDiu GPR64:$hi, tblockaddress:$lo)>, ISA_MIPS3, GPR_64,
- SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tjumptable:$lo))),
- (DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tconstpool:$lo))),
- (DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
-
- def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))),
- (DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tblockaddress:$lo))),
- (DADDiu GPR64:$hi, tblockaddress:$lo)>, ISA_MIPS3, GPR_64,
- SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tjumptable:$lo))),
- (DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tconstpool:$lo))),
- (DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
-
- def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))),
- (DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tblockaddress:$lo))),
- (DADDiu GPR64:$hi, tblockaddress:$lo)>, ISA_MIPS3, GPR_64,
- SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tjumptable:$lo))),
- (DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tconstpool:$lo))),
- (DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
- def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaltlsaddr:$lo))),
- (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>, ISA_MIPS3, GPR_64,
- SYM_64;
-}
+def : MipsPat<(MipsHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>;
+def : MipsPat<(MipsHi tblockaddress:$in), (LUi64 tblockaddress:$in)>;
+def : MipsPat<(MipsHi tjumptable:$in), (LUi64 tjumptable:$in)>;
+def : MipsPat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>;
+def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>;
+def : MipsPat<(MipsHi texternalsym:$in), (LUi64 texternalsym:$in)>;
+
+def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>;
+def : MipsPat<(MipsLo tblockaddress:$in), (DADDiu ZERO_64, tblockaddress:$in)>;
+def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>;
+def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>;
+def : MipsPat<(MipsLo tglobaltlsaddr:$in),
+ (DADDiu ZERO_64, tglobaltlsaddr:$in)>;
+def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>;
+
+def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)),
+ (DADDiu GPR64:$hi, tglobaladdr:$lo)>;
+def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)),
+ (DADDiu GPR64:$hi, tblockaddress:$lo)>;
+def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)),
+ (DADDiu GPR64:$hi, tjumptable:$lo)>;
+def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)),
+ (DADDiu GPR64:$hi, tconstpool:$lo)>;
+def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)),
+ (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>;
+
+def : WrapperPat<tglobaladdr, DADDiu, GPR64>;
+def : WrapperPat<tconstpool, DADDiu, GPR64>;
+def : WrapperPat<texternalsym, DADDiu, GPR64>;
+def : WrapperPat<tblockaddress, DADDiu, GPR64>;
+def : WrapperPat<tjumptable, DADDiu, GPR64>;
+def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>;
+
+defm : BrcondPats<GPR64, BEQ64, BNE64, SLT64, SLTu64, SLTi64, SLTiu64,
+ ZERO_64>;
-// gp_rel relocs
-def : MipsPat<(add GPR64:$gp, (MipsGPRel tglobaladdr:$in)),
- (DADDiu GPR64:$gp, tglobaladdr:$in)>, ISA_MIPS3, ABI_N64;
-def : MipsPat<(add GPR64:$gp, (MipsGPRel tconstpool:$in)),
- (DADDiu GPR64:$gp, tconstpool:$in)>, ISA_MIPS3, ABI_N64;
-
-def : WrapperPat<tglobaladdr, DADDiu, GPR64>, ISA_MIPS3, GPR_64;
-def : WrapperPat<tconstpool, DADDiu, GPR64>, ISA_MIPS3, GPR_64;
-def : WrapperPat<texternalsym, DADDiu, GPR64>, ISA_MIPS3, GPR_64;
-def : WrapperPat<tblockaddress, DADDiu, GPR64>, ISA_MIPS3, GPR_64;
-def : WrapperPat<tjumptable, DADDiu, GPR64>, ISA_MIPS3, GPR_64;
-def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>, ISA_MIPS3, GPR_64;
-
-
-defm : BrcondPats<GPR64, BEQ64, BEQ, BNE64, SLT64, SLTu64, SLTi64, SLTiu64,
- ZERO_64>, ISA_MIPS3, GPR_64;
def : MipsPat<(brcond (i32 (setlt i64:$lhs, 1)), bb:$dst),
- (BLEZ64 i64:$lhs, bb:$dst)>, ISA_MIPS3, GPR_64;
+ (BLEZ64 i64:$lhs, bb:$dst)>;
def : MipsPat<(brcond (i32 (setgt i64:$lhs, -1)), bb:$dst),
- (BGEZ64 i64:$lhs, bb:$dst)>, ISA_MIPS3, GPR_64;
+ (BGEZ64 i64:$lhs, bb:$dst)>;
// setcc patterns
-let AdditionalPredicates = [NotInMicroMips] in {
- defm : SeteqPats<GPR64, SLTiu64, XOR64, SLTu64, ZERO_64>, ISA_MIPS3, GPR_64;
- defm : SetlePats<GPR64, XORi, SLT64, SLTu64>, ISA_MIPS3, GPR_64;
- defm : SetgtPats<GPR64, SLT64, SLTu64>, ISA_MIPS3, GPR_64;
- defm : SetgePats<GPR64, XORi, SLT64, SLTu64>, ISA_MIPS3, GPR_64;
- defm : SetgeImmPats<GPR64, XORi, SLTi64, SLTiu64>, ISA_MIPS3, GPR_64;
-}
+defm : SeteqPats<GPR64, SLTiu64, XOR64, SLTu64, ZERO_64>;
+defm : SetlePats<GPR64, SLT64, SLTu64>;
+defm : SetgtPats<GPR64, SLT64, SLTu64>;
+defm : SetgePats<GPR64, SLT64, SLTu64>;
+defm : SetgeImmPats<GPR64, SLTi64, SLTiu64>;
+
// truncate
def : MipsPat<(trunc (assertsext GPR64:$src)),
- (EXTRACT_SUBREG GPR64:$src, sub_32)>, ISA_MIPS3, GPR_64;
-// The forward compatibility strategy employed by MIPS requires us to treat
-// values as being sign extended to an infinite number of bits. This allows
-// existing software to run without modification on any future MIPS
-// implementation (e.g. 128-bit, or 1024-bit). Being compatible with this
-// strategy requires that truncation acts as a sign-extension for values being
-// fed into instructions operating on 32-bit values. Such instructions have
-// undefined results if this is not true.
-// For our case, this means that we can't issue an extract_subreg for nodes
-// such as (trunc:i32 (assertzext:i64 X, i32)), because the sign-bit of the
-// lower subreg would not be replicated into the upper half.
-def : MipsPat<(trunc (assertzext_lt_i32 GPR64:$src)),
- (EXTRACT_SUBREG GPR64:$src, sub_32)>, ISA_MIPS3, GPR_64;
+ (EXTRACT_SUBREG GPR64:$src, sub_32)>;
+def : MipsPat<(trunc (assertzext GPR64:$src)),
+ (EXTRACT_SUBREG GPR64:$src, sub_32)>;
def : MipsPat<(i32 (trunc GPR64:$src)),
- (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>, ISA_MIPS3, GPR_64;
+ (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>;
// variable shift instructions patterns
def : MipsPat<(shl GPR64:$rt, (i32 (trunc GPR64:$rs))),
- (DSLLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>,
- ISA_MIPS3, GPR_64;
+ (DSLLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>;
def : MipsPat<(srl GPR64:$rt, (i32 (trunc GPR64:$rs))),
- (DSRLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>,
- ISA_MIPS3, GPR_64;
+ (DSRLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>;
def : MipsPat<(sra GPR64:$rt, (i32 (trunc GPR64:$rs))),
- (DSRAV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>,
- ISA_MIPS3, GPR_64;
+ (DSRAV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>;
def : MipsPat<(rotr GPR64:$rt, (i32 (trunc GPR64:$rs))),
- (DROTRV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>,
- ISA_MIPS3, GPR_64;
+ (DROTRV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>;
// 32-to-64-bit extension
def : MipsPat<(i64 (anyext GPR32:$src)),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>,
- ISA_MIPS3, GPR_64;
-def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>,
- ISA_MIPS3, GPR_64;
-def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>, ISA_MIPS3,
- GPR_64;
-
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsPat<(i64 (zext GPR32:$src)), (DEXT64_32 GPR32:$src, 0, 32)>,
- ISA_MIPS64R2, GPR_64;
- def : MipsPat<(i64 (zext (i32 (shl GPR32:$rt, immZExt5:$imm)))),
- (CINS64_32 GPR32:$rt, imm:$imm, (immZExt5To31 imm:$imm))>,
- ISA_MIPS64R2, GPR_64, ASE_MIPS64_CNMIPS;
-}
+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>;
+def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>;
+def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>;
// Sign extend in register
def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)),
- (SLL64_64 GPR64:$src)>, ISA_MIPS3, GPR_64;
+ (SLL64_64 GPR64:$src)>;
// bswap MipsPattern
-def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>, ISA_MIPS64R2;
+def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>;
// Carry pattern
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs),
- (DSUBu GPR64:$lhs, GPR64:$rhs)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs),
+ (DSUBu GPR64:$lhs, GPR64:$rhs)>;
+let AdditionalPredicates = [NotDSP] in {
def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs),
- (DADDu GPR64:$lhs, GPR64:$rhs)>, ISA_MIPS3, ASE_NOT_DSP, GPR_64;
+ (DADDu GPR64:$lhs, GPR64:$rhs)>;
def : MipsPat<(addc GPR64:$lhs, immSExt16:$imm),
- (DADDiu GPR64:$lhs, imm:$imm)>, ISA_MIPS3, ASE_NOT_DSP, GPR_64;
+ (DADDiu GPR64:$lhs, imm:$imm)>;
}
// Octeon bbit0/bbit1 MipsPattern
+let Predicates = [HasMips64, HasCnMips] in {
def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst),
- (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>,
- ISA_MIPS64R2, ASE_MIPS64_CNMIPS;
+ (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>;
def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst),
- (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>,
- ISA_MIPS64R2, ASE_MIPS64_CNMIPS;
+ (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>;
def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst),
- (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>,
- ISA_MIPS64R2, ASE_MIPS64_CNMIPS;
+ (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>;
def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst),
- (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>,
- ISA_MIPS64R2, ASE_MIPS64_CNMIPS;
-def : MipsPat<(brcond (i32 (seteq (and i32:$lhs, PowerOf2LO_i32:$mask), 0)), bb:$dst),
- (BBIT0 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), i32:$lhs, sub_32),
- (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ISA_MIPS64R2,
- ASE_MIPS64_CNMIPS;
-def : MipsPat<(brcond (i32 (setne (and i32:$lhs, PowerOf2LO_i32:$mask), 0)), bb:$dst),
- (BBIT1 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), i32:$lhs, sub_32),
- (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ISA_MIPS64R2,
- ASE_MIPS64_CNMIPS;
+ (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>;
+}
// Atomic load patterns.
-def : MipsPat<(atomic_load_8 addr:$a), (LB64 addr:$a)>, ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_load_16 addr:$a), (LH64 addr:$a)>, ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_load_32 addr:$a), (LW64 addr:$a)>, ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_load_64 addr:$a), (LD addr:$a)>, ISA_MIPS3, GPR_64;
+def : MipsPat<(atomic_load_8 addr:$a), (LB64 addr:$a)>;
+def : MipsPat<(atomic_load_16 addr:$a), (LH64 addr:$a)>;
+def : MipsPat<(atomic_load_32 addr:$a), (LW64 addr:$a)>;
+def : MipsPat<(atomic_load_64 addr:$a), (LD addr:$a)>;
// Atomic store patterns.
-def : MipsPat<(atomic_store_8 addr:$a, GPR64:$v), (SB64 GPR64:$v, addr:$a)>,
- ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_store_16 addr:$a, GPR64:$v), (SH64 GPR64:$v, addr:$a)>,
- ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_store_32 addr:$a, GPR64:$v), (SW64 GPR64:$v, addr:$a)>,
- ISA_MIPS3, GPR_64;
-def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>,
- ISA_MIPS3, GPR_64;
-
-// Patterns used for matching away redundant sign extensions.
-// MIPS32 arithmetic instructions sign extend their result implicitly.
-def : MipsPat<(i64 (sext (i32 (add GPR32:$src, immSExt16:$imm16)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (ADDiu GPR32:$src, immSExt16:$imm16), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (add GPR32:$src, GPR32:$src2)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (ADDu GPR32:$src, GPR32:$src2), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (SUBu GPR32:$src, GPR32:$src2), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (MUL GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS3_NOT_32R6_64R6;
-def : MipsPat<(i64 (sext (i32 (MipsMFHI ACC64:$src)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (PseudoMFHI ACC64:$src), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (MipsMFLO ACC64:$src)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (PseudoMFLO ACC64:$src), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (shl GPR32:$src, immZExt5:$imm5)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (SLL GPR32:$src, immZExt5:$imm5), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (shl GPR32:$src, GPR32:$src2)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (SLLV GPR32:$src, GPR32:$src2), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (srl GPR32:$src, immZExt5:$imm5)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (SRL GPR32:$src, immZExt5:$imm5), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (srl GPR32:$src, GPR32:$src2)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (SRLV GPR32:$src, GPR32:$src2), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (sra GPR32:$src, immZExt5:$imm5)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (SRA GPR32:$src, immZExt5:$imm5), sub_32)>;
-def : MipsPat<(i64 (sext (i32 (sra GPR32:$src, GPR32:$src2)))),
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
- (SRAV GPR32:$src, GPR32:$src2), sub_32)>;
+def : MipsPat<(atomic_store_8 addr:$a, GPR64:$v), (SB64 GPR64:$v, addr:$a)>;
+def : MipsPat<(atomic_store_16 addr:$a, GPR64:$v), (SH64 GPR64:$v, addr:$a)>;
+def : MipsPat<(atomic_store_32 addr:$a, GPR64:$v), (SW64 GPR64:$v, addr:$a)>;
+def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>;
//===----------------------------------------------------------------------===//
// Instruction aliases
//===----------------------------------------------------------------------===//
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsInstAlias<"move $dst, $src",
- (OR64 GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>,
- GPR_64;
- def : MipsInstAlias<"move $dst, $src",
- (DADDu GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>,
- GPR_64;
- def : MipsInstAlias<"dadd $rs, $rt, $imm",
- (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
- 0>, ISA_MIPS3_NOT_32R6_64R6;
- def : MipsInstAlias<"dadd $rs, $imm",
- (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
- 0>, ISA_MIPS3_NOT_32R6_64R6;
- def : MipsInstAlias<"daddu $rs, $rt, $imm",
- (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
- 0>, ISA_MIPS3;
- def : MipsInstAlias<"daddu $rs, $imm",
- (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
- 0>, ISA_MIPS3;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi64, GPR64Opnd, imm64>,
- ISA_MIPS3, GPR_64;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi64, GPR64Opnd, imm64>,
- ISA_MIPS3, GPR_64;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi64, GPR64Opnd, imm64>,
- ISA_MIPS3, GPR_64;
-}
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsInstAlias<"dneg $rt, $rs",
- (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
- ISA_MIPS3;
- def : MipsInstAlias<"dneg $rt",
- (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 1>,
- ISA_MIPS3;
- def : MipsInstAlias<"dnegu $rt, $rs",
- (DSUBu GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
- ISA_MIPS3;
- def : MipsInstAlias<"dnegu $rt",
- (DSUBu GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 1>,
- ISA_MIPS3;
-}
+def : MipsInstAlias<"move $dst, $src",
+ (OR64 GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>,
+ GPR_64;
+def : MipsInstAlias<"move $dst, $src",
+ (DADDu GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>,
+ GPR_64;
+def : MipsInstAlias<"daddu $rs, $rt, $imm",
+ (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
+ 0>, ISA_MIPS3;
+def : MipsInstAlias<"dadd $rs, $rt, $imm",
+ (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
+ 0>, ISA_MIPS3_NOT_32R6_64R6;
+def : MipsInstAlias<"daddu $rs, $imm",
+ (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>, ISA_MIPS3;
+def : MipsInstAlias<"dadd $rs, $imm",
+ (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>, ISA_MIPS3_NOT_32R6_64R6;
+def : MipsInstAlias<"dsll $rd, $rt, $rs",
+ (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
+ ISA_MIPS3;
+def : MipsInstAlias<"dneg $rt, $rs",
+ (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
+ ISA_MIPS3;
+def : MipsInstAlias<"dneg $rt",
+ (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 0>,
+ ISA_MIPS3;
+def : MipsInstAlias<"dnegu $rt, $rs",
+ (DSUBu GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
+ ISA_MIPS3;
+def : MipsInstAlias<"dsubu $rt, $rs, $imm",
+ (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs,
+ InvertedImOperand64:$imm), 0>, ISA_MIPS3;
def : MipsInstAlias<"dsubi $rs, $rt, $imm",
(DADDi GPR64Opnd:$rs, GPR64Opnd:$rt,
InvertedImOperand64:$imm),
@@ -933,63 +616,29 @@ def : MipsInstAlias<"dsub $rs, $imm",
(DADDi GPR64Opnd:$rs, GPR64Opnd:$rs,
InvertedImOperand64:$imm),
0>, ISA_MIPS3_NOT_32R6_64R6;
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsInstAlias<"dsubu $rt, $rs, $imm",
- (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs,
- InvertedImOperand64:$imm), 0>, ISA_MIPS3;
- def : MipsInstAlias<"dsubu $rs, $imm",
- (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs,
- InvertedImOperand64:$imm), 0>, ISA_MIPS3;
-}
+def : MipsInstAlias<"dsubu $rs, $imm",
+ (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs,
+ InvertedImOperand64:$imm),
+ 0>, ISA_MIPS3;
def : MipsInstAlias<"dsra $rd, $rt, $rs",
(DSRAV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
ISA_MIPS3;
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsInstAlias<"dsll $rd, $rt, $rs",
- (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
- ISA_MIPS3;
- def : MipsInstAlias<"dsrl $rd, $rt, $rs",
- (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
- ISA_MIPS3;
- def : MipsInstAlias<"dsrl $rd, $rt",
- (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rd, GPR32Opnd:$rt), 0>,
- ISA_MIPS3;
- def : MipsInstAlias<"dsll $rd, $rt",
- (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rd, GPR32Opnd:$rt), 0>,
- ISA_MIPS3;
- def : MipsInstAlias<"dins $rt, $rs, $pos, $size",
- (DINSM GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5:$pos,
- uimm_range_2_64:$size), 0>, ISA_MIPS64R2;
- def : MipsInstAlias<"dins $rt, $rs, $pos, $size",
- (DINSU GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32:$pos,
- uimm5_plus1:$size), 0>, ISA_MIPS64R2;
- def : MipsInstAlias<"dext $rt, $rs, $pos, $size",
- (DEXTM GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5:$pos,
- uimm5_plus33:$size), 0>, ISA_MIPS64R2;
- def : MipsInstAlias<"dext $rt, $rs, $pos, $size",
- (DEXTU GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32:$pos,
- uimm5_plus1:$size), 0>, ISA_MIPS64R2;
- def : MipsInstAlias<"jalr.hb $rs", (JALR_HB64 RA_64, GPR64Opnd:$rs), 1>,
- ISA_MIPS64;
+def : MipsInstAlias<"dsrl $rd, $rt, $rs",
+ (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
+ ISA_MIPS3;
+
// Two operand (implicit 0 selector) versions:
- def : MipsInstAlias<"dmtc0 $rt, $rd",
- (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>;
- def : MipsInstAlias<"dmfc0 $rt, $rd",
- (DMFC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>;
- def : MipsInstAlias<"dmfgc0 $rt, $rd",
- (DMFGC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>,
- ISA_MIPS64R5, ASE_VIRT;
- def : MipsInstAlias<"dmtgc0 $rt, $rd",
- (DMTGC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>,
- ISA_MIPS64R5, ASE_VIRT;
-}
+def : MipsInstAlias<"dmfc0 $rt, $rd", (DMFC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"dmtc0 $rt, $rd", (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>;
def : MipsInstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, COP2Opnd:$rd, 0), 0>;
def : MipsInstAlias<"dmtc2 $rt, $rd", (DMTC2 COP2Opnd:$rd, GPR64Opnd:$rt, 0), 0>;
-def : MipsInstAlias<"synciobdma", (SYNC 0x2), 0>, ASE_MIPS64_CNMIPS;
-def : MipsInstAlias<"syncs", (SYNC 0x6), 0>, ASE_MIPS64_CNMIPS;
-def : MipsInstAlias<"syncw", (SYNC 0x4), 0>, ASE_MIPS64_CNMIPS;
-def : MipsInstAlias<"syncws", (SYNC 0x5), 0>, ASE_MIPS64_CNMIPS;
+let Predicates = [HasMips64, HasCnMips] in {
+def : MipsInstAlias<"synciobdma", (SYNC 0x2), 0>;
+def : MipsInstAlias<"syncs", (SYNC 0x6), 0>;
+def : MipsInstAlias<"syncw", (SYNC 0x4), 0>;
+def : MipsInstAlias<"syncws", (SYNC 0x5), 0>;
+}
// cnMIPS Aliases.
@@ -1007,21 +656,21 @@ def : MipsInstAlias<"bbit1 $rs, $p, $offset",
def : MipsInstAlias<"exts $rt, $rs, $pos, $lenm1",
(EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rs,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_MIPS64_CNMIPS;
+ ASE_CNMIPS;
def : MipsInstAlias<"exts $rt, $pos, $lenm1",
(EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rt,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_MIPS64_CNMIPS;
+ ASE_CNMIPS;
// cins with $pos 32-63 in converted to cins32 with $pos 0-31
def : MipsInstAlias<"cins $rt, $rs, $pos, $lenm1",
(CINS32 GPR64Opnd:$rt, GPR64Opnd:$rs,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_MIPS64_CNMIPS;
+ ASE_CNMIPS;
def : MipsInstAlias<"cins $rt, $pos, $lenm1",
(CINS32 GPR64Opnd:$rt, GPR64Opnd:$rt,
uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>,
- ASE_MIPS64_CNMIPS;
+ ASE_CNMIPS;
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions
@@ -1036,116 +685,3 @@ def LoadAddrReg64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins mem:$addr),
"dla\t$rt, $addr">;
def LoadAddrImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rt), (ins imm64:$imm64),
"dla\t$rt, $imm64">;
-
-def DMULImmMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt,
- simm32_relaxed:$imm),
- "dmul\t$rs, $rt, $imm">,
- ISA_MIPS3_NOT_32R6_64R6;
-def DMULOMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt,
- GPR64Opnd:$rd),
- "dmulo\t$rs, $rt, $rd">,
- ISA_MIPS3_NOT_32R6_64R6;
-def DMULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt,
- GPR64Opnd:$rd),
- "dmulou\t$rs, $rt, $rd">,
- ISA_MIPS3_NOT_32R6_64R6;
-
-def DMULMacro : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rs, GPR64Opnd:$rt,
- GPR64Opnd:$rd),
- "dmul\t$rs, $rt, $rd"> {
- let InsnPredicates = [HasMips3, NotMips64r6, NotCnMips];
-}
-
-let AdditionalPredicates = [NotInMicroMips] in {
- def DSDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
- (ins GPR64Opnd:$rs, GPR64Opnd:$rt),
- "ddiv\t$rd, $rs, $rt">,
- ISA_MIPS3_NOT_32R6_64R6;
- def DSDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
- (ins GPR64Opnd:$rs, imm64:$imm),
- "ddiv\t$rd, $rs, $imm">,
- ISA_MIPS3_NOT_32R6_64R6;
- def DUDivMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
- (ins GPR64Opnd:$rs, GPR64Opnd:$rt),
- "ddivu\t$rd, $rs, $rt">,
- ISA_MIPS3_NOT_32R6_64R6;
- def DUDivIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
- (ins GPR64Opnd:$rs, imm64:$imm),
- "ddivu\t$rd, $rs, $imm">,
- ISA_MIPS3_NOT_32R6_64R6;
-
- // GAS expands 'div' and 'ddiv' differently when the destination
- // register is $zero and the instruction is in the two operand
- // form. 'ddiv' gets expanded, while 'div' is not expanded.
-
- def : MipsInstAlias<"ddiv $rs, $rt", (DSDivMacro GPR64Opnd:$rs,
- GPR64Opnd:$rs,
- GPR64Opnd:$rt), 0>,
- ISA_MIPS3_NOT_32R6_64R6;
- def : MipsInstAlias<"ddiv $rd, $imm", (DSDivIMacro GPR64Opnd:$rd,
- GPR64Opnd:$rd,
- imm64:$imm), 0>,
- ISA_MIPS3_NOT_32R6_64R6;
-
- // GAS expands 'divu' and 'ddivu' differently when the destination
- // register is $zero and the instruction is in the two operand
- // form. 'ddivu' gets expanded, while 'divu' is not expanded.
-
- def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR64Opnd:$rt,
- GPR64Opnd:$rt,
- GPR64Opnd:$rs), 0>,
- ISA_MIPS3_NOT_32R6_64R6;
- def : MipsInstAlias<"ddivu $rd, $imm", (DUDivIMacro GPR64Opnd:$rd,
- GPR64Opnd:$rd,
- imm64:$imm), 0>,
- ISA_MIPS3_NOT_32R6_64R6;
- def DSRemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
- (ins GPR64Opnd:$rs, GPR64Opnd:$rt),
- "drem\t$rd, $rs, $rt">,
- ISA_MIPS3_NOT_32R6_64R6;
- def DSRemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
- (ins GPR64Opnd:$rs, simm32_relaxed:$imm),
- "drem\t$rd, $rs, $imm">,
- ISA_MIPS3_NOT_32R6_64R6;
- def DURemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
- (ins GPR64Opnd:$rs, GPR64Opnd:$rt),
- "dremu\t$rd, $rs, $rt">,
- ISA_MIPS3_NOT_32R6_64R6;
- def DURemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
- (ins GPR64Opnd:$rs, simm32_relaxed:$imm),
- "dremu\t$rd, $rs, $imm">,
- ISA_MIPS3_NOT_32R6_64R6;
- def : MipsInstAlias<"drem $rt, $rs", (DSRemMacro GPR64Opnd:$rt,
- GPR64Opnd:$rt,
- GPR64Opnd:$rs), 0>,
- ISA_MIPS3_NOT_32R6_64R6;
- def : MipsInstAlias<"drem $rd, $imm", (DSRemIMacro GPR64Opnd:$rd,
- GPR64Opnd:$rd,
- simm32_relaxed:$imm), 0>,
- ISA_MIPS3_NOT_32R6_64R6;
- def : MipsInstAlias<"dremu $rt, $rs", (DURemMacro GPR64Opnd:$rt,
- GPR64Opnd:$rt,
- GPR64Opnd:$rs), 0>,
- ISA_MIPS3_NOT_32R6_64R6;
- def : MipsInstAlias<"dremu $rd, $imm", (DURemIMacro GPR64Opnd:$rd,
- GPR64Opnd:$rd,
- simm32_relaxed:$imm), 0>,
- ISA_MIPS3_NOT_32R6_64R6;
-}
-
-def NORImm64 : NORIMM_DESC_BASE<GPR64Opnd, imm64>, GPR_64;
-def : MipsInstAlias<"nor\t$rs, $imm", (NORImm64 GPR64Opnd:$rs, GPR64Opnd:$rs,
- imm64:$imm)>, GPR_64;
-def SLTImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs),
- (ins GPR64Opnd:$rt, imm64:$imm),
- "slt\t$rs, $rt, $imm">, GPR_64;
-def : MipsInstAlias<"slt\t$rs, $imm", (SLTImm64 GPR64Opnd:$rs, GPR64Opnd:$rs,
- imm64:$imm)>, GPR_64;
-def SLTUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rs),
- (ins GPR64Opnd:$rt, imm64:$imm),
- "sltu\t$rs, $rt, $imm">, GPR_64;
-def : MipsInstAlias<"sltu\t$rs, $imm", (SLTUImm64 GPR64Opnd:$rs, GPR64Opnd:$rs,
- imm64:$imm)>, GPR_64;
-
-def : MipsInstAlias<"rdhwr $rt, $rs",
- (RDHWR64 GPR64Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, GPR_64;
diff --git a/gnu/llvm/lib/Target/Mips/MipsInstrInfo.td b/gnu/llvm/lib/Target/Mips/MipsInstrInfo.td
index 46721e6cb9e..8977bf1212f 100644
--- a/gnu/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/gnu/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -21,7 +21,7 @@ def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
SDTCisSameAs<1, 2>,
SDTCisSameAs<3, 4>,
SDTCisInt<4>]>;
-def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
def SDT_MFLOHI : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVT<1, untyped>]>;
def SDT_MTLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>,
@@ -59,22 +59,16 @@ def MipsTailCall : SDNode<"MipsISD::TailCall", SDT_MipsJmpLink,
// Hi and Lo nodes are used to handle global addresses. Used on
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
// static model. (nothing to do with Mips Registers Hi and Lo)
-
-// Hi is the odd node out, on MIPS64 it can expand to either daddiu when
-// using static relocations with 64 bit symbols, or lui when using 32 bit
-// symbols.
-def MipsHigher : SDNode<"MipsISD::Higher", SDTIntUnaryOp>;
-def MipsHighest : SDNode<"MipsISD::Highest", SDTIntUnaryOp>;
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>;
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
-
def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>;
-// Hi node for accessing the GOT.
-def MipsGotHi : SDNode<"MipsISD::GotHi", SDTIntUnaryOp>;
+// TlsGd node is used to handle General Dynamic TLS
+def MipsTlsGd : SDNode<"MipsISD::TlsGd", SDTIntUnaryOp>;
-// Hi node for handling TLS offsets
-def MipsTlsHi : SDNode<"MipsISD::TlsHi", SDTIntUnaryOp>;
+// TprelHi and TprelLo nodes are used to handle Local Exec TLS
+def MipsTprelHi : SDNode<"MipsISD::TprelHi", SDTIntUnaryOp>;
+def MipsTprelLo : SDNode<"MipsISD::TprelLo", SDTIntUnaryOp>;
// Thread pointer
def MipsThreadPointer: SDNode<"MipsISD::ThreadPointer", SDT_MipsThreadPointer>;
@@ -134,7 +128,6 @@ def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain,SDNPSideEffect]>;
def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>;
def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>;
-def MipsCIns : SDNode<"MipsISD::CIns", SDT_Ext>;
def MipsLWL : SDNode<"MipsISD::LWL", SDTMipsLoadLR,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
@@ -164,8 +157,6 @@ def HasMips3_32r2 : Predicate<"Subtarget->hasMips3_32r2()">,
AssemblerPredicate<"FeatureMips3_32r2">;
def HasMips3 : Predicate<"Subtarget->hasMips3()">,
AssemblerPredicate<"FeatureMips3">;
-def NotMips3 : Predicate<"!Subtarget->hasMips3()">,
- AssemblerPredicate<"!FeatureMips3">;
def HasMips4_32 : Predicate<"Subtarget->hasMips4_32()">,
AssemblerPredicate<"FeatureMips4_32">;
def NotMips4_32 : Predicate<"!Subtarget->hasMips4_32()">,
@@ -188,38 +179,26 @@ def IsGP64bit : Predicate<"Subtarget->isGP64bit()">,
AssemblerPredicate<"FeatureGP64Bit">;
def IsGP32bit : Predicate<"!Subtarget->isGP64bit()">,
AssemblerPredicate<"!FeatureGP64Bit">;
-def IsPTR64bit : Predicate<"Subtarget->isABI_N64()">,
- AssemblerPredicate<"FeaturePTR64Bit">;
-def IsPTR32bit : Predicate<"!Subtarget->isABI_N64()">,
- AssemblerPredicate<"!FeaturePTR64Bit">;
def HasMips64 : Predicate<"Subtarget->hasMips64()">,
AssemblerPredicate<"FeatureMips64">;
def NotMips64 : Predicate<"!Subtarget->hasMips64()">,
AssemblerPredicate<"!FeatureMips64">;
def HasMips64r2 : Predicate<"Subtarget->hasMips64r2()">,
AssemblerPredicate<"FeatureMips64r2">;
-def HasMips64r5 : Predicate<"Subtarget->hasMips64r5()">,
- AssemblerPredicate<"FeatureMips64r5">;
def HasMips64r6 : Predicate<"Subtarget->hasMips64r6()">,
AssemblerPredicate<"FeatureMips64r6">;
def NotMips64r6 : Predicate<"!Subtarget->hasMips64r6()">,
AssemblerPredicate<"!FeatureMips64r6">;
+def HasMicroMips32r6 : Predicate<"Subtarget->inMicroMips32r6Mode()">,
+ AssemblerPredicate<"FeatureMicroMips,FeatureMips32r6">;
+def HasMicroMips64r6 : Predicate<"Subtarget->inMicroMips64r6Mode()">,
+ AssemblerPredicate<"FeatureMicroMips,FeatureMips64r6">;
def InMips16Mode : Predicate<"Subtarget->inMips16Mode()">,
AssemblerPredicate<"FeatureMips16">;
-def NotInMips16Mode : Predicate<"!Subtarget->inMips16Mode()">,
- AssemblerPredicate<"!FeatureMips16">;
def HasCnMips : Predicate<"Subtarget->hasCnMips()">,
AssemblerPredicate<"FeatureCnMips">;
-def NotCnMips : Predicate<"!Subtarget->hasCnMips()">,
- AssemblerPredicate<"!FeatureCnMips">;
-def IsSym32 : Predicate<"Subtarget->HasSym32()">,
- AssemblerPredicate<"FeatureSym32">;
-def IsSym64 : Predicate<"!Subtarget->HasSym32()">,
- AssemblerPredicate<"!FeatureSym32">;
-def IsN64 : Predicate<"Subtarget->isABI_N64()">;
-def IsNotN64 : Predicate<"!Subtarget->isABI_N64()">;
-def RelocNotPIC : Predicate<"!TM.isPositionIndependent()">;
-def RelocPIC : Predicate<"TM.isPositionIndependent()">;
+def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">;
+def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">;
def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">;
def HasStdEnc : Predicate<"Subtarget->hasStandardEncoding()">,
AssemblerPredicate<"!FeatureMips16">;
@@ -233,26 +212,11 @@ def IsBE : Predicate<"!Subtarget->isLittle()">;
def IsNotNaCl : Predicate<"!Subtarget->isTargetNaCl()">;
def UseTCCInDIV : AssemblerPredicate<"FeatureUseTCCInDIV">;
def HasEVA : Predicate<"Subtarget->hasEVA()">,
- AssemblerPredicate<"FeatureEVA">;
+ AssemblerPredicate<"FeatureEVA,FeatureMips32r2">;
def HasMSA : Predicate<"Subtarget->hasMSA()">,
AssemblerPredicate<"FeatureMSA">;
-def HasMadd4 : Predicate<"!Subtarget->disableMadd4()">,
- AssemblerPredicate<"!FeatureMadd4">;
-def HasMT : Predicate<"Subtarget->hasMT()">,
- AssemblerPredicate<"FeatureMT">;
-def UseIndirectJumpsHazard : Predicate<"Subtarget->useIndirectJumpsHazard()">,
- AssemblerPredicate<"FeatureUseIndirectJumpsHazard">;
-def NoIndirectJumpGuards : Predicate<"!Subtarget->useIndirectJumpsHazard()">,
- AssemblerPredicate<"!FeatureUseIndirectJumpsHazard">;
-def HasCRC : Predicate<"Subtarget->hasCRC()">,
- AssemblerPredicate<"FeatureCRC">;
-def HasVirt : Predicate<"Subtarget->hasVirt()">,
- AssemblerPredicate<"FeatureVirt">;
-def HasGINV : Predicate<"Subtarget->hasGINV()">,
- AssemblerPredicate<"FeatureGINV">;
-// TODO: Add support for FPOpFusion::Standard
-def AllowFPOpFusion : Predicate<"TM.Options.AllowFPOpFusion =="
- " FPOpFusion::Fast">;
+
+
//===----------------------------------------------------------------------===//
// Mips GPR size adjectives.
// They are mutually exclusive.
@@ -261,17 +225,6 @@ def AllowFPOpFusion : Predicate<"TM.Options.AllowFPOpFusion =="
class GPR_32 { list<Predicate> GPRPredicates = [IsGP32bit]; }
class GPR_64 { list<Predicate> GPRPredicates = [IsGP64bit]; }
-class PTR_32 { list<Predicate> PTRPredicates = [IsPTR32bit]; }
-class PTR_64 { list<Predicate> PTRPredicates = [IsPTR64bit]; }
-
-//===----------------------------------------------------------------------===//
-// Mips Symbol size adjectives.
-// They are mutally exculsive.
-//===----------------------------------------------------------------------===//
-
-class SYM_32 { list<Predicate> SYMPredicates = [IsSym32]; }
-class SYM_64 { list<Predicate> SYMPredicates = [IsSym64]; }
-
//===----------------------------------------------------------------------===//
// Mips ISA/ASE membership and instruction group membership adjectives.
// They are mutually exclusive.
@@ -282,226 +235,109 @@ class SYM_64 { list<Predicate> SYMPredicates = [IsSym64]; }
// subtractive predicate will hopefully keep us under the 32 predicate
// limit long enough to develop an alternative way to handle P1||P2
// predicates.
-class ISA_MIPS1 {
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS1_NOT_MIPS3 {
- list<Predicate> InsnPredicates = [NotMips3];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
class ISA_MIPS1_NOT_4_32 {
list<Predicate> InsnPredicates = [NotMips4_32];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
class ISA_MIPS1_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS2 {
- list<Predicate> InsnPredicates = [HasMips2];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
+class ISA_MIPS2 { list<Predicate> InsnPredicates = [HasMips2]; }
class ISA_MIPS2_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [HasMips2, NotMips32r6, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS3 {
- list<Predicate> InsnPredicates = [HasMips3];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
+class ISA_MIPS3 { list<Predicate> InsnPredicates = [HasMips3]; }
class ISA_MIPS3_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [HasMips3, NotMips32r6, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS32 {
- list<Predicate> InsnPredicates = [HasMips32];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
+class ISA_MIPS32 { list<Predicate> InsnPredicates = [HasMips32]; }
class ISA_MIPS32_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [HasMips32, NotMips32r6, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS32R2 {
- list<Predicate> InsnPredicates = [HasMips32r2];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
+class ISA_MIPS32R2 { list<Predicate> InsnPredicates = [HasMips32r2]; }
class ISA_MIPS32R2_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [HasMips32r2, NotMips32r6, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS32R5 {
- list<Predicate> InsnPredicates = [HasMips32r5];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS64 {
- list<Predicate> InsnPredicates = [HasMips64];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
+class ISA_MIPS32R5 { list<Predicate> InsnPredicates = [HasMips32r5]; }
+class ISA_MIPS64 { list<Predicate> InsnPredicates = [HasMips64]; }
class ISA_MIPS64_NOT_64R6 {
list<Predicate> InsnPredicates = [HasMips64, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS64R2 {
- list<Predicate> InsnPredicates = [HasMips64r2];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS64R5 {
- list<Predicate> InsnPredicates = [HasMips64r5];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS32R6 {
- list<Predicate> InsnPredicates = [HasMips32r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MIPS64R6 {
- list<Predicate> InsnPredicates = [HasMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-class ISA_MICROMIPS {
- list<Predicate> EncodingPredicates = [InMicroMips];
-}
-class ISA_MICROMIPS32R5 {
- list<Predicate> InsnPredicates = [HasMips32r5];
- list<Predicate> EncodingPredicates = [InMicroMips];
}
+class ISA_MIPS64R2 { list<Predicate> InsnPredicates = [HasMips64r2]; }
+class ISA_MIPS32R6 { list<Predicate> InsnPredicates = [HasMips32r6]; }
+class ISA_MIPS64R6 { list<Predicate> InsnPredicates = [HasMips64r6]; }
+class ISA_MICROMIPS { list<Predicate> InsnPredicates = [InMicroMips]; }
class ISA_MICROMIPS32R6 {
- list<Predicate> InsnPredicates = [HasMips32r6];
- list<Predicate> EncodingPredicates = [InMicroMips];
+ list<Predicate> InsnPredicates = [HasMicroMips32r6];
}
class ISA_MICROMIPS64R6 {
- list<Predicate> InsnPredicates = [HasMips64r6];
- list<Predicate> EncodingPredicates = [InMicroMips];
+ list<Predicate> InsnPredicates = [HasMicroMips64r6];
}
class ISA_MICROMIPS32_NOT_MIPS32R6 {
- list<Predicate> InsnPredicates = [NotMips32r6];
- list<Predicate> EncodingPredicates = [InMicroMips];
+ list<Predicate> InsnPredicates = [InMicroMips, NotMips32r6];
}
-class ASE_EVA { list<Predicate> ASEPredicate = [HasEVA]; }
-// The portions of MIPS-III that were also added to MIPS32
-class INSN_MIPS3_32 {
- list<Predicate> InsnPredicates = [HasMips3_32];
- list<Predicate> EncodingPredicates = [HasStdEnc];
+class INSN_EVA { list<Predicate> InsnPredicates = [HasEVA]; }
+class INSN_EVA_NOT_32R6_64R6 {
+ list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6, HasEVA];
}
+// The portions of MIPS-III that were also added to MIPS32
+class INSN_MIPS3_32 { list<Predicate> InsnPredicates = [HasMips3_32]; }
+
// The portions of MIPS-III that were also added to MIPS32 but were removed in
// MIPS32r6 and MIPS64r6.
class INSN_MIPS3_32_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [HasMips3_32, NotMips32r6, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
// The portions of MIPS-III that were also added to MIPS32
-class INSN_MIPS3_32R2 {
- list<Predicate> InsnPredicates = [HasMips3_32r2];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-
-// The portions of MIPS-IV that were also added to MIPS32.
-class INSN_MIPS4_32 {
- list <Predicate> InsnPredicates = [HasMips4_32];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
+class INSN_MIPS3_32R2 { list<Predicate> InsnPredicates = [HasMips3_32r2]; }
// The portions of MIPS-IV that were also added to MIPS32 but were removed in
// MIPS32r6 and MIPS64r6.
class INSN_MIPS4_32_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [HasMips4_32, NotMips32r6, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
// The portions of MIPS-IV that were also added to MIPS32r2 but were removed in
// MIPS32r6 and MIPS64r6.
class INSN_MIPS4_32R2_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [HasMips4_32r2, NotMips32r6, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
-}
-
-// The portions of MIPS-IV that were also added to MIPS32r2.
-class INSN_MIPS4_32R2 {
- list<Predicate> InsnPredicates = [HasMips4_32r2];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
// The portions of MIPS-V that were also added to MIPS32r2 but were removed in
// MIPS32r6 and MIPS64r6.
class INSN_MIPS5_32R2_NOT_32R6_64R6 {
list<Predicate> InsnPredicates = [HasMips5_32r2, NotMips32r6, NotMips64r6];
- list<Predicate> EncodingPredicates = [HasStdEnc];
}
class ASE_CNMIPS {
- list<Predicate> ASEPredicate = [HasCnMips];
-}
-
-class NOT_ASE_CNMIPS {
- list<Predicate> ASEPredicate = [NotCnMips];
-}
-
-class ASE_MIPS64_CNMIPS {
- list<Predicate> ASEPredicate = [HasMips64, HasCnMips];
+ list<Predicate> InsnPredicates = [HasCnMips];
}
class ASE_MSA {
- list<Predicate> ASEPredicate = [HasMSA];
+ list<Predicate> InsnPredicates = [HasMSA];
}
class ASE_MSA_NOT_MSA64 {
- list<Predicate> ASEPredicate = [HasMSA, NotMips64];
+ list<Predicate> InsnPredicates = [HasMSA, NotMips64];
}
class ASE_MSA64 {
- list<Predicate> ASEPredicate = [HasMSA, HasMips64];
-}
-
-class ASE_MT {
- list <Predicate> ASEPredicate = [HasMT];
-}
-
-class ASE_CRC {
- list <Predicate> ASEPredicate = [HasCRC];
-}
-
-class ASE_VIRT {
- list <Predicate> ASEPredicate = [HasVirt];
-}
-
-class ASE_GINV {
- list <Predicate> ASEPredicate = [HasGINV];
+ list<Predicate> InsnPredicates = [HasMSA, HasMips64];
}
// Class used for separating microMIPSr6 and microMIPS (r3) instruction.
// It can be used only on instructions that doesn't inherit PredicateControl.
-class ISA_MICROMIPS_NOT_32R6 : PredicateControl {
- let InsnPredicates = [NotMips32r6];
- let EncodingPredicates = [InMicroMips];
-}
-
-class ASE_NOT_DSP {
- list<Predicate> ASEPredicate = [NotDSP];
-}
-
-class MADD4 {
- list<Predicate> AdditionalPredicates = [HasMadd4];
-}
-
-// Classses used for separating expansions that differ based on the ABI in
-// use.
-class ABI_N64 {
- list<Predicate> AdditionalPredicates = [IsN64];
-}
-
-class ABI_NOT_N64 {
- list<Predicate> AdditionalPredicates = [IsNotN64];
-}
-
-class FPOP_FUSION_FAST {
- list <Predicate> AdditionalPredicates = [AllowFPOpFusion];
+class ISA_MICROMIPS_NOT_32R6_64R6 : PredicateControl {
+ let InsnPredicates = [InMicroMips, NotMips32r6, NotMips64r6];
}
//===----------------------------------------------------------------------===//
-class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl;
+class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl {
+ let EncodingPredicates = [HasStdEnc];
+}
class MipsInstAlias<string Asm, dag Result, bit Emit = 0b1> :
InstAlias<Asm, Result, Emit>, PredicateControl;
@@ -512,17 +348,14 @@ class IsCommutable {
class IsBranch {
bit isBranch = 1;
- bit isCTI = 1;
}
class IsReturn {
bit isReturn = 1;
- bit isCTI = 1;
}
class IsCall {
bit isCall = 1;
- bit isCTI = 1;
}
class IsTailCall {
@@ -532,7 +365,6 @@ class IsTailCall {
bit isBarrier = 1;
bit hasExtraSrcRegAllocReq = 1;
bit isCodeGenOnly = 1;
- bit isCTI = 1;
}
class IsAsCheapAsAMove {
@@ -553,22 +385,13 @@ include "MipsInstrFormats.td"
// Mips Operand, Complex Patterns and Transformations Definitions.
//===----------------------------------------------------------------------===//
-class ConstantSImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
- int Offset = 0> : AsmOperandClass {
- let Name = "ConstantSImm" # Bits # "_" # Offset;
- let RenderMethod = "addConstantSImmOperands<" # Bits # ", " # Offset # ">";
- let PredicateMethod = "isConstantSImm<" # Bits # ", " # Offset # ">";
- let SuperClasses = Supers;
- let DiagnosticType = "SImm" # Bits # "_" # Offset;
-}
-
-class SimmLslAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
- int Shift = 0> : AsmOperandClass {
- let Name = "Simm" # Bits # "_Lsl" # Shift;
+class ConstantSImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
+ : AsmOperandClass {
+ let Name = "ConstantSImm" # Bits;
let RenderMethod = "addImmOperands";
- let PredicateMethod = "isScaledSImm<" # Bits # ", " # Shift # ">";
+ let PredicateMethod = "isConstantSImm<" # Bits # ">";
let SuperClasses = Supers;
- let DiagnosticType = "SImm" # Bits # "_Lsl" # Shift;
+ let DiagnosticType = "SImm" # Bits;
}
class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
@@ -580,218 +403,49 @@ class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
let DiagnosticType = "UImm" # Bits # "_" # Offset;
}
-class ConstantUImmRangeAsmOperandClass<int Bottom, int Top,
- list<AsmOperandClass> Supers = []>
- : AsmOperandClass {
- let Name = "ConstantUImmRange" # Bottom # "_" # Top;
- let RenderMethod = "addImmOperands";
- let PredicateMethod = "isConstantUImmRange<" # Bottom # ", " # Top # ">";
- let SuperClasses = Supers;
- let DiagnosticType = "UImmRange" # Bottom # "_" # Top;
-}
-
-class SImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
- : AsmOperandClass {
- let Name = "SImm" # Bits;
- let RenderMethod = "addSImmOperands<" # Bits # ">";
- let PredicateMethod = "isSImm<" # Bits # ">";
- let SuperClasses = Supers;
- let DiagnosticType = "SImm" # Bits;
-}
-
-class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
- : AsmOperandClass {
- let Name = "UImm" # Bits;
- let RenderMethod = "addUImmOperands<" # Bits # ">";
- let PredicateMethod = "isUImm<" # Bits # ">";
- let SuperClasses = Supers;
- let DiagnosticType = "UImm" # Bits;
-}
-
-// Generic case - only to support certain assembly pseudo instructions.
-class UImmAnyAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
- : AsmOperandClass {
- let Name = "ImmAny";
- let RenderMethod = "addConstantUImmOperands<32>";
- let PredicateMethod = "isSImm<" # Bits # ">";
- let SuperClasses = Supers;
- let DiagnosticType = "ImmAny";
-}
-
-// AsmOperandClasses require a strict ordering which is difficult to manage
-// as a hierarchy. Instead, we use a linear ordering and impose an order that
-// is in some places arbitrary.
-//
-// Here the rules that are in use:
-// * Wider immediates are a superset of narrower immediates:
-// uimm4 < uimm5 < uimm6
-// * For the same bit-width, unsigned immediates are a superset of signed
-// immediates::
-// simm4 < uimm4 < simm5 < uimm5
-// * For the same upper-bound, signed immediates are a superset of unsigned
-// immediates:
-// uimm3 < simm4 < uimm4 < simm4
-// * Modified immediates are a superset of ordinary immediates:
-// uimm5 < uimm5_plus1 (1..32) < uimm5_plus32 (32..63) < uimm6
-// The term 'superset' starts to break down here since the uimm5_plus* classes
-// are not true supersets of uimm5 (but they are still subsets of uimm6).
-// * 'Relaxed' immediates are supersets of the corresponding unsigned immediate.
-// uimm16 < uimm16_relaxed
-// * The codeGen pattern type is arbitrarily ordered.
-// uimm5 < uimm5_64, and uimm5 < vsplat_uimm5
-// This is entirely arbitrary. We need an ordering and what we pick is
-// unimportant since only one is possible for a given mnemonic.
-
-def UImm32CoercedAsmOperandClass : UImmAnyAsmOperandClass<33, []> {
- let Name = "UImm32_Coerced";
- let DiagnosticType = "UImm32_Coerced";
-}
-def SImm32RelaxedAsmOperandClass
- : SImmAsmOperandClass<32, [UImm32CoercedAsmOperandClass]> {
- let Name = "SImm32_Relaxed";
- let PredicateMethod = "isAnyImm<33>";
- let DiagnosticType = "SImm32_Relaxed";
-}
-def SImm32AsmOperandClass
- : SImmAsmOperandClass<32, [SImm32RelaxedAsmOperandClass]>;
-def ConstantUImm26AsmOperandClass
- : ConstantUImmAsmOperandClass<26, [SImm32AsmOperandClass]>;
-def ConstantUImm20AsmOperandClass
- : ConstantUImmAsmOperandClass<20, [ConstantUImm26AsmOperandClass]>;
-def ConstantSImm19Lsl2AsmOperandClass : AsmOperandClass {
- let Name = "SImm19Lsl2";
- let RenderMethod = "addImmOperands";
- let PredicateMethod = "isScaledSImm<19, 2>";
- let SuperClasses = [ConstantUImm20AsmOperandClass];
- let DiagnosticType = "SImm19_Lsl2";
-}
-def UImm16RelaxedAsmOperandClass
- : UImmAsmOperandClass<16, [ConstantUImm20AsmOperandClass]> {
- let Name = "UImm16_Relaxed";
- let PredicateMethod = "isAnyImm<16>";
- let DiagnosticType = "UImm16_Relaxed";
-}
-// Similar to the relaxed classes which take an SImm and render it as
-// an UImm, this takes a UImm and renders it as an SImm.
-def UImm16AltRelaxedAsmOperandClass
- : SImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]> {
- let Name = "UImm16_AltRelaxed";
- let PredicateMethod = "isUImm<16>";
- let DiagnosticType = "UImm16_AltRelaxed";
-}
-// FIXME: One of these should probably have UImm16AsmOperandClass as the
-// superclass instead of UImm16RelaxedasmOPerandClass.
-def UImm16AsmOperandClass
- : UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>;
-def SImm16RelaxedAsmOperandClass
- : SImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]> {
- let Name = "SImm16_Relaxed";
- let PredicateMethod = "isAnyImm<16>";
- let DiagnosticType = "SImm16_Relaxed";
-}
-def SImm16AsmOperandClass
- : SImmAsmOperandClass<16, [SImm16RelaxedAsmOperandClass]>;
-def ConstantSImm10Lsl3AsmOperandClass : AsmOperandClass {
- let Name = "SImm10Lsl3";
- let RenderMethod = "addImmOperands";
- let PredicateMethod = "isScaledSImm<10, 3>";
- let SuperClasses = [SImm16AsmOperandClass];
- let DiagnosticType = "SImm10_Lsl3";
-}
-def ConstantSImm10Lsl2AsmOperandClass : AsmOperandClass {
- let Name = "SImm10Lsl2";
- let RenderMethod = "addImmOperands";
- let PredicateMethod = "isScaledSImm<10, 2>";
- let SuperClasses = [ConstantSImm10Lsl3AsmOperandClass];
- let DiagnosticType = "SImm10_Lsl2";
-}
-def ConstantSImm11AsmOperandClass
- : ConstantSImmAsmOperandClass<11, [ConstantSImm10Lsl2AsmOperandClass]>;
-def ConstantSImm10Lsl1AsmOperandClass : AsmOperandClass {
- let Name = "SImm10Lsl1";
- let RenderMethod = "addImmOperands";
- let PredicateMethod = "isScaledSImm<10, 1>";
- let SuperClasses = [ConstantSImm11AsmOperandClass];
- let DiagnosticType = "SImm10_Lsl1";
-}
def ConstantUImm10AsmOperandClass
- : ConstantUImmAsmOperandClass<10, [ConstantSImm10Lsl1AsmOperandClass]>;
-def ConstantSImm10AsmOperandClass
- : ConstantSImmAsmOperandClass<10, [ConstantUImm10AsmOperandClass]>;
-def ConstantSImm9AsmOperandClass
- : ConstantSImmAsmOperandClass<9, [ConstantSImm10AsmOperandClass]>;
-def ConstantSImm7Lsl2AsmOperandClass : AsmOperandClass {
- let Name = "SImm7Lsl2";
- let RenderMethod = "addImmOperands";
- let PredicateMethod = "isScaledSImm<7, 2>";
- let SuperClasses = [ConstantSImm9AsmOperandClass];
- let DiagnosticType = "SImm7_Lsl2";
-}
+ : ConstantUImmAsmOperandClass<10, []>;
def ConstantUImm8AsmOperandClass
- : ConstantUImmAsmOperandClass<8, [ConstantSImm7Lsl2AsmOperandClass]>;
-def ConstantUImm7Sub1AsmOperandClass
- : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass], -1> {
- // Specify the names since the -1 offset causes invalid identifiers otherwise.
- let Name = "UImm7_N1";
- let DiagnosticType = "UImm7_N1";
-}
+ : ConstantUImmAsmOperandClass<8, [ConstantUImm10AsmOperandClass]>;
def ConstantUImm7AsmOperandClass
- : ConstantUImmAsmOperandClass<7, [ConstantUImm7Sub1AsmOperandClass]>;
-def ConstantUImm6Lsl2AsmOperandClass : AsmOperandClass {
- let Name = "UImm6Lsl2";
- let RenderMethod = "addImmOperands";
- let PredicateMethod = "isScaledUImm<6, 2>";
- let SuperClasses = [ConstantUImm7AsmOperandClass];
- let DiagnosticType = "UImm6_Lsl2";
-}
+ : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass]>;
def ConstantUImm6AsmOperandClass
- : ConstantUImmAsmOperandClass<6, [ConstantUImm6Lsl2AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>;
def ConstantSImm6AsmOperandClass
- : ConstantSImmAsmOperandClass<6, [ConstantUImm6AsmOperandClass]>;
+ : ConstantSImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>;
+def ConstantUImm5Plus1AsmOperandClass
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 1>;
+def ConstantUImm5Plus32AsmOperandClass
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32>;
+def ConstantUImm5Plus33AsmOperandClass
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 33>;
+def ConstantUImm5Plus32NormalizeAsmOperandClass
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32> {
+ let Name = "ConstantUImm5_32_Norm";
+ // We must also subtract 32 when we render the operand.
+ let RenderMethod = "addConstantUImmOperands<5, 32, -32>";
+}
def ConstantUImm5Lsl2AsmOperandClass : AsmOperandClass {
let Name = "UImm5Lsl2";
let RenderMethod = "addImmOperands";
let PredicateMethod = "isScaledUImm<5, 2>";
- let SuperClasses = [ConstantSImm6AsmOperandClass];
+ let SuperClasses = [ConstantUImm6AsmOperandClass];
let DiagnosticType = "UImm5_Lsl2";
}
-def ConstantUImm5_Range2_64AsmOperandClass
- : ConstantUImmRangeAsmOperandClass<2, 64, [ConstantUImm5Lsl2AsmOperandClass]>;
-def ConstantUImm5Plus33AsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm5_Range2_64AsmOperandClass],
- 33>;
def ConstantUImm5ReportUImm6AsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus33AsmOperandClass]> {
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]> {
let Name = "ConstantUImm5_0_Report_UImm6";
let DiagnosticType = "UImm5_0_Report_UImm6";
}
-def ConstantUImm5Plus32AsmOperandClass
- : ConstantUImmAsmOperandClass<
- 5, [ConstantUImm5ReportUImm6AsmOperandClass], 32>;
-def ConstantUImm5Plus32NormalizeAsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus32AsmOperandClass], 32> {
- let Name = "ConstantUImm5_32_Norm";
- // We must also subtract 32 when we render the operand.
- let RenderMethod = "addConstantUImmOperands<5, 32, -32>";
-}
-def ConstantUImm5Plus1ReportUImm6AsmOperandClass
- : ConstantUImmAsmOperandClass<
- 5, [ConstantUImm5Plus32NormalizeAsmOperandClass], 1>{
- let Name = "ConstantUImm5_Plus1_Report_UImm6";
-}
-def ConstantUImm5Plus1AsmOperandClass
- : ConstantUImmAsmOperandClass<
- 5, [ConstantUImm5Plus1ReportUImm6AsmOperandClass], 1>;
def ConstantUImm5AsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus1AsmOperandClass]>;
-def ConstantSImm5AsmOperandClass
- : ConstantSImmAsmOperandClass<5, [ConstantUImm5AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]>;
def ConstantUImm4AsmOperandClass
- : ConstantUImmAsmOperandClass<4, [ConstantSImm5AsmOperandClass]>;
-def ConstantSImm4AsmOperandClass
- : ConstantSImmAsmOperandClass<4, [ConstantUImm4AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<
+ 4, [ConstantUImm5AsmOperandClass,
+ ConstantUImm5Plus32AsmOperandClass,
+ ConstantUImm5Plus32NormalizeAsmOperandClass]>;
def ConstantUImm3AsmOperandClass
- : ConstantUImmAsmOperandClass<3, [ConstantSImm4AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<3, [ConstantUImm4AsmOperandClass]>;
def ConstantUImm2Plus1AsmOperandClass
: ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass], 1>;
def ConstantUImm2AsmOperandClass
@@ -806,9 +460,6 @@ def ConstantImmzAsmOperandClass : AsmOperandClass {
let DiagnosticType = "Immz";
}
-def Simm19Lsl2AsmOperand
- : SimmLslAsmOperandClass<19, [], 2>;
-
def MipsJumpTargetAsmOperand : AsmOperandClass {
let Name = "JumpTarget";
let ParserMethod = "parseJumpTarget";
@@ -827,12 +478,6 @@ def brtarget : Operand<OtherVT> {
let DecoderMethod = "DecodeBranchTarget";
let ParserMatchClass = MipsJumpTargetAsmOperand;
}
-def brtarget1SImm16 : Operand<OtherVT> {
- let EncoderMethod = "getBranchTargetOpValue1SImm16";
- let OperandType = "OPERAND_PCREL";
- let DecoderMethod = "DecodeBranchTarget1SImm16";
- let ParserMatchClass = MipsJumpTargetAsmOperand;
-}
def calltarget : Operand<iPTR> {
let EncoderMethod = "getJumpTargetOpValue";
let ParserMatchClass = MipsJumpTargetAsmOperand;
@@ -840,10 +485,22 @@ def calltarget : Operand<iPTR> {
def imm64: Operand<i64>;
+def simm6 : Operand<i32> {
+ let ParserMatchClass = ConstantSImm6AsmOperandClass;
+ let OperandType = "OPERAND_IMMEDIATE";
+}
+def simm9 : Operand<i32>;
+def simm10 : Operand<i32>;
+def simm11 : Operand<i32>;
+
+def simm16 : Operand<i32> {
+ let DecoderMethod= "DecodeSimm16";
+}
+
def simm19_lsl2 : Operand<i32> {
let EncoderMethod = "getSimm19Lsl2Encoding";
let DecoderMethod = "DecodeSimm19Lsl2";
- let ParserMatchClass = Simm19Lsl2AsmOperand;
+ let ParserMatchClass = MipsJumpTargetAsmOperand;
}
def simm18_lsl3 : Operand<i32> {
@@ -852,223 +509,91 @@ def simm18_lsl3 : Operand<i32> {
let ParserMatchClass = MipsJumpTargetAsmOperand;
}
+def simm20 : Operand<i32>;
+def simm32 : Operand<i32>;
+
+def uimm20 : Operand<i32> {
+}
+
+def simm16_64 : Operand<i64> {
+ let DecoderMethod = "DecodeSimm16";
+}
+
// Zero
def uimmz : Operand<i32> {
- let PrintMethod = "printUImm<0>";
+ let PrintMethod = "printUnsignedImm";
let ParserMatchClass = ConstantImmzAsmOperandClass;
}
-// size operand of ins instruction
-def uimm_range_2_64 : Operand<i32> {
- let PrintMethod = "printUImm<6, 2>";
- let EncoderMethod = "getSizeInsEncoding";
- let DecoderMethod = "DecodeInsSize";
- let ParserMatchClass = ConstantUImm5_Range2_64AsmOperandClass;
-}
-
// Unsigned Operands
-foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10, 20, 26} in
+foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10} in
def uimm # I : Operand<i32> {
- let PrintMethod = "printUImm<" # I # ">";
+ let PrintMethod = "printUnsignedImm";
let ParserMatchClass =
!cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass");
}
def uimm2_plus1 : Operand<i32> {
- let PrintMethod = "printUImm<2, 1>";
+ let PrintMethod = "printUnsignedImm";
let EncoderMethod = "getUImmWithOffsetEncoding<2, 1>";
let DecoderMethod = "DecodeUImmWithOffset<2, 1>";
let ParserMatchClass = ConstantUImm2Plus1AsmOperandClass;
}
def uimm5_plus1 : Operand<i32> {
- let PrintMethod = "printUImm<5, 1>";
+ let PrintMethod = "printUnsignedImm";
let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>";
let DecoderMethod = "DecodeUImmWithOffset<5, 1>";
let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass;
}
-def uimm5_plus1_report_uimm6 : Operand<i32> {
- let PrintMethod = "printUImm<6, 1>";
- let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>";
- let DecoderMethod = "DecodeUImmWithOffset<5, 1>";
- let ParserMatchClass = ConstantUImm5Plus1ReportUImm6AsmOperandClass;
-}
-
def uimm5_plus32 : Operand<i32> {
- let PrintMethod = "printUImm<5, 32>";
+ let PrintMethod = "printUnsignedImm";
let ParserMatchClass = ConstantUImm5Plus32AsmOperandClass;
}
def uimm5_plus33 : Operand<i32> {
- let PrintMethod = "printUImm<5, 33>";
+ let PrintMethod = "printUnsignedImm";
let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>";
let DecoderMethod = "DecodeUImmWithOffset<5, 1>";
let ParserMatchClass = ConstantUImm5Plus33AsmOperandClass;
}
-def uimm5_inssize_plus1 : Operand<i32> {
- let PrintMethod = "printUImm<6>";
- let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass;
- let EncoderMethod = "getSizeInsEncoding";
- let DecoderMethod = "DecodeInsSize";
-}
-
def uimm5_plus32_normalize : Operand<i32> {
- let PrintMethod = "printUImm<5>";
+ let PrintMethod = "printUnsignedImm";
let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass;
}
def uimm5_lsl2 : Operand<OtherVT> {
let EncoderMethod = "getUImm5Lsl2Encoding";
- let DecoderMethod = "DecodeUImmWithOffsetAndScale<5, 0, 4>";
+ let DecoderMethod = "DecodeUImm5lsl2";
let ParserMatchClass = ConstantUImm5Lsl2AsmOperandClass;
}
def uimm5_plus32_normalize_64 : Operand<i64> {
- let PrintMethod = "printUImm<5>";
+ let PrintMethod = "printUnsignedImm";
let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass;
}
-def uimm6_lsl2 : Operand<OtherVT> {
- let EncoderMethod = "getUImm6Lsl2Encoding";
- let DecoderMethod = "DecodeUImmWithOffsetAndScale<6, 0, 4>";
- let ParserMatchClass = ConstantUImm6Lsl2AsmOperandClass;
-}
-
-foreach I = {16} in
- def uimm # I : Operand<i32> {
- let PrintMethod = "printUImm<" # I # ">";
- let ParserMatchClass =
- !cast<AsmOperandClass>("UImm" # I # "AsmOperandClass");
- }
-
-// Like uimm16_64 but coerces simm16 to uimm16.
-def uimm16_relaxed : Operand<i32> {
- let PrintMethod = "printUImm<16>";
- let ParserMatchClass =
- !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass");
-}
-
foreach I = {5} in
def uimm # I # _64 : Operand<i64> {
- let PrintMethod = "printUImm<" # I # ">";
+ let PrintMethod = "printUnsignedImm";
let ParserMatchClass =
!cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass");
}
-foreach I = {16} in
- def uimm # I # _64 : Operand<i64> {
- let PrintMethod = "printUImm<" # I # ">";
- let ParserMatchClass =
- !cast<AsmOperandClass>("UImm" # I # "AsmOperandClass");
- }
-
-// Like uimm16_64 but coerces simm16 to uimm16.
-def uimm16_64_relaxed : Operand<i64> {
- let PrintMethod = "printUImm<16>";
- let ParserMatchClass =
- !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass");
-}
-
-def uimm16_altrelaxed : Operand<i32> {
- let PrintMethod = "printUImm<16>";
- let ParserMatchClass =
- !cast<AsmOperandClass>("UImm16AltRelaxedAsmOperandClass");
-}
-// Like uimm5 but reports a less confusing error for 32-63 when
-// an instruction alias permits that.
-def uimm5_report_uimm6 : Operand<i32> {
- let PrintMethod = "printUImm<6>";
- let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass;
-}
-
// Like uimm5_64 but reports a less confusing error for 32-63 when
// an instruction alias permits that.
def uimm5_64_report_uimm6 : Operand<i64> {
- let PrintMethod = "printUImm<5>";
+ let PrintMethod = "printUnsignedImm";
let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass;
}
-foreach I = {1, 2, 3, 4} in
- def uimm # I # _ptr : Operand<iPTR> {
- let PrintMethod = "printUImm<" # I # ">";
- let ParserMatchClass =
- !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass");
- }
-
-foreach I = {1, 2, 3, 4, 5, 6, 8} in
- def vsplat_uimm # I : Operand<vAny> {
- let PrintMethod = "printUImm<" # I # ">";
- let ParserMatchClass =
- !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass");
- }
-
-// Signed operands
-foreach I = {4, 5, 6, 9, 10, 11} in
- def simm # I : Operand<i32> {
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">";
- let ParserMatchClass =
- !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass");
- }
-
-foreach I = {1, 2, 3} in
- def simm10_lsl # I : Operand<i32> {
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<10, " # I # ">";
- let ParserMatchClass =
- !cast<AsmOperandClass>("ConstantSImm10Lsl" # I # "AsmOperandClass");
- }
-
-foreach I = {10} in
- def simm # I # _64 : Operand<i64> {
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">";
- let ParserMatchClass =
- !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass");
- }
-
-foreach I = {5, 10} in
- def vsplat_simm # I : Operand<vAny> {
- let ParserMatchClass =
- !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass");
- }
-
-def simm7_lsl2 : Operand<OtherVT> {
- let EncoderMethod = "getSImm7Lsl2Encoding";
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ", 0, 4>";
- let ParserMatchClass = ConstantSImm7Lsl2AsmOperandClass;
+def uimm16 : Operand<i32> {
+ let PrintMethod = "printUnsignedImm";
}
-foreach I = {16, 32} in
- def simm # I : Operand<i32> {
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">";
- let ParserMatchClass = !cast<AsmOperandClass>("SImm" # I # "AsmOperandClass");
- }
-
-// Like simm16 but coerces uimm16 to simm16.
-def simm16_relaxed : Operand<i32> {
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>";
- let ParserMatchClass = !cast<AsmOperandClass>("SImm16RelaxedAsmOperandClass");
-}
-
-def simm16_64 : Operand<i64> {
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>";
- let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass");
-}
-
-// like simm32 but coerces simm32 to uimm32.
-def uimm32_coerced : Operand<i32> {
- let ParserMatchClass = !cast<AsmOperandClass>("UImm32CoercedAsmOperandClass");
-}
-// Like simm32 but coerces uimm32 to simm32.
-def simm32_relaxed : Operand<i32> {
- let DecoderMethod = "DecodeSImmWithOffsetAndScale<32>";
- let ParserMatchClass = !cast<AsmOperandClass>("SImm32RelaxedAsmOperandClass");
-}
-
-// This is almost the same as a uimm7 but 0x7f is interpreted as -1.
-def li16_imm : Operand<i32> {
- let DecoderMethod = "DecodeLi16Imm";
- let ParserMatchClass = ConstantUImm7Sub1AsmOperandClass;
+def pcrel16 : Operand<i32> {
}
def MipsMemAsmOperand : AsmOperandClass {
@@ -1082,44 +607,22 @@ def MipsMemSimm9AsmOperand : AsmOperandClass {
let RenderMethod = "addMemOperands";
let ParserMethod = "parseMemOperand";
let PredicateMethod = "isMemWithSimmOffset<9>";
- let DiagnosticType = "MemSImm9";
}
-def MipsMemSimm10AsmOperand : AsmOperandClass {
- let Name = "MemOffsetSimm10";
+def MipsMemSimm9GPRAsmOperand : AsmOperandClass {
+ let Name = "MemOffsetSimm9GPR";
let SuperClasses = [MipsMemAsmOperand];
let RenderMethod = "addMemOperands";
let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithSimmOffset<10>";
- let DiagnosticType = "MemSImm10";
+ let PredicateMethod = "isMemWithSimmOffsetGPR<9>";
}
-def MipsMemSimm12AsmOperand : AsmOperandClass {
- let Name = "MemOffsetSimm12";
- let SuperClasses = [MipsMemAsmOperand];
- let RenderMethod = "addMemOperands";
- let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithSimmOffset<12>";
- let DiagnosticType = "MemSImm12";
-}
-
-foreach I = {1, 2, 3} in
- def MipsMemSimm10Lsl # I # AsmOperand : AsmOperandClass {
- let Name = "MemOffsetSimm10_" # I;
- let SuperClasses = [MipsMemAsmOperand];
- let RenderMethod = "addMemOperands";
- let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithSimmOffset<10, " # I # ">";
- let DiagnosticType = "MemSImm10Lsl" # I;
- }
-
def MipsMemSimm11AsmOperand : AsmOperandClass {
let Name = "MemOffsetSimm11";
let SuperClasses = [MipsMemAsmOperand];
let RenderMethod = "addMemOperands";
let ParserMethod = "parseMemOperand";
let PredicateMethod = "isMemWithSimmOffset<11>";
- let DiagnosticType = "MemSImm11";
}
def MipsMemSimm16AsmOperand : AsmOperandClass {
@@ -1128,16 +631,6 @@ def MipsMemSimm16AsmOperand : AsmOperandClass {
let RenderMethod = "addMemOperands";
let ParserMethod = "parseMemOperand";
let PredicateMethod = "isMemWithSimmOffset<16>";
- let DiagnosticType = "MemSImm16";
-}
-
-def MipsMemSimmPtrAsmOperand : AsmOperandClass {
- let Name = "MemOffsetSimmPtr";
- let SuperClasses = [MipsMemAsmOperand];
- let RenderMethod = "addMemOperands";
- let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithPtrSizeOffset";
- let DiagnosticType = "MemSImmPtr";
}
def MipsInvertedImmoperand : AsmOperandClass {
@@ -1171,52 +664,30 @@ def mem_msa : mem_generic {
let EncoderMethod = "getMSAMemEncoding";
}
-def simm12 : Operand<i32> {
- let DecoderMethod = "DecodeSimm12";
-}
-
def mem_simm9 : mem_generic {
let MIOperandInfo = (ops ptr_rc, simm9);
let EncoderMethod = "getMemEncoding";
let ParserMatchClass = MipsMemSimm9AsmOperand;
}
-def mem_simm10 : mem_generic {
- let MIOperandInfo = (ops ptr_rc, simm10);
+def mem_simm9gpr : mem_generic {
+ let MIOperandInfo = (ops ptr_rc, simm9);
let EncoderMethod = "getMemEncoding";
- let ParserMatchClass = MipsMemSimm10AsmOperand;
+ let ParserMatchClass = MipsMemSimm9GPRAsmOperand;
}
-foreach I = {1, 2, 3} in
- def mem_simm10_lsl # I : mem_generic {
- let MIOperandInfo = (ops ptr_rc, !cast<Operand>("simm10_lsl" # I));
- let EncoderMethod = "getMemEncoding<" # I # ">";
- let ParserMatchClass =
- !cast<AsmOperandClass>("MipsMemSimm10Lsl" # I # "AsmOperand");
- }
-
def mem_simm11 : mem_generic {
let MIOperandInfo = (ops ptr_rc, simm11);
let EncoderMethod = "getMemEncoding";
let ParserMatchClass = MipsMemSimm11AsmOperand;
}
-def mem_simm12 : mem_generic {
- let MIOperandInfo = (ops ptr_rc, simm12);
- let EncoderMethod = "getMemEncoding";
- let ParserMatchClass = MipsMemSimm12AsmOperand;
-}
-
def mem_simm16 : mem_generic {
let MIOperandInfo = (ops ptr_rc, simm16);
let EncoderMethod = "getMemEncoding";
let ParserMatchClass = MipsMemSimm16AsmOperand;
}
-def mem_simmptr : mem_generic {
- let ParserMatchClass = MipsMemSimmPtrAsmOperand;
-}
-
def mem_ea : Operand<iPTR> {
let PrintMethod = "printMemOperandEA";
let MIOperandInfo = (ops ptr_rc, simm16);
@@ -1260,8 +731,9 @@ def immSExt8 : PatLeaf<(imm), [{ return isInt<8>(N->getSExtValue()); }]>;
// e.g. addi, andi
def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>;
-// Node immediate fits as 7-bit zero extended on target immediate.
-def immZExt7 : PatLeaf<(imm), [{ return isUInt<7>(N->getZExtValue()); }]>;
+// Node immediate fits as 15-bit sign extended on target immediate.
+// e.g. addi, andi
+def immSExt15 : PatLeaf<(imm), [{ return isInt<15>(N->getSExtValue()); }]>;
// Node immediate fits as 16-bit zero extended on target immediate.
// The LO16 param means that only the lower 16 bits of the node
@@ -1275,64 +747,19 @@ def immZExt16 : PatLeaf<(imm), [{
}], LO16>;
// Immediate can be loaded with LUi (32-bit int with lower 16-bit cleared).
-def immSExt32Low16Zero : PatLeaf<(imm), [{
+def immLow16Zero : PatLeaf<(imm), [{
int64_t Val = N->getSExtValue();
return isInt<32>(Val) && !(Val & 0xffff);
}]>;
-// Zero-extended 32-bit unsigned int with lower 16-bit cleared.
-def immZExt32Low16Zero : PatLeaf<(imm), [{
- uint64_t Val = N->getZExtValue();
- return isUInt<32>(Val) && !(Val & 0xffff);
-}]>;
-
-// Note immediate fits as a 32 bit signed extended on target immediate.
-def immSExt32 : PatLeaf<(imm), [{ return isInt<32>(N->getSExtValue()); }]>;
-
-// Note immediate fits as a 32 bit zero extended on target immediate.
-def immZExt32 : PatLeaf<(imm), [{ return isUInt<32>(N->getZExtValue()); }]>;
-
// shamt field must fit in 5 bits.
def immZExt5 : ImmLeaf<i32, [{return Imm == (Imm & 0x1f);}]>;
-def immZExt5Plus1 : PatLeaf<(imm), [{
- return isUInt<5>(N->getZExtValue() - 1);
-}]>;
-def immZExt5Plus32 : PatLeaf<(imm), [{
- return isUInt<5>(N->getZExtValue() - 32);
-}]>;
-def immZExt5Plus33 : PatLeaf<(imm), [{
- return isUInt<5>(N->getZExtValue() - 33);
-}]>;
-
-def immZExt5To31 : SDNodeXForm<imm, [{
- return getImm(N, 31 - N->getZExtValue());
-}]>;
-
// True if (N + 1) fits in 16-bit field.
def immSExt16Plus1 : PatLeaf<(imm), [{
return isInt<17>(N->getSExtValue()) && isInt<16>(N->getSExtValue() + 1);
}]>;
-def immZExtRange2To64 : PatLeaf<(imm), [{
- return isUInt<7>(N->getZExtValue()) && (N->getZExtValue() >= 2) &&
- (N->getZExtValue() <= 64);
-}]>;
-
-def ORiPred : PatLeaf<(imm), [{
- return isUInt<16>(N->getZExtValue()) && !isInt<16>(N->getSExtValue());
-}], LO16>;
-
-def LUiPred : PatLeaf<(imm), [{
- int64_t Val = N->getSExtValue();
- return !isInt<16>(Val) && isInt<32>(Val) && !(Val & 0xffff);
-}]>;
-
-def LUiORiPred : PatLeaf<(imm), [{
- int64_t SVal = N->getSExtValue();
- return isInt<32>(SVal) && (SVal & 0xffff);
-}]>;
-
// Mips Address Mode! SDNode frameindex could possibily be a match
// since load and store instructions from stack used it.
def addr :
@@ -1341,16 +768,13 @@ def addr :
def addrRegImm :
ComplexPattern<iPTR, 2, "selectAddrRegImm", [frameindex]>;
+def addrRegReg :
+ ComplexPattern<iPTR, 2, "selectAddrRegReg", [frameindex]>;
+
def addrDefault :
ComplexPattern<iPTR, 2, "selectAddrDefault", [frameindex]>;
-def addrimm10 : ComplexPattern<iPTR, 2, "selectIntAddrSImm10", [frameindex]>;
-def addrimm10lsl1 : ComplexPattern<iPTR, 2, "selectIntAddrSImm10Lsl1",
- [frameindex]>;
-def addrimm10lsl2 : ComplexPattern<iPTR, 2, "selectIntAddrSImm10Lsl2",
- [frameindex]>;
-def addrimm10lsl3 : ComplexPattern<iPTR, 2, "selectIntAddrSImm10Lsl3",
- [frameindex]>;
+def addrimm10 : ComplexPattern<iPTR, 2, "selectIntAddrMSA", [frameindex]>;
//===----------------------------------------------------------------------===//
// Instructions specific format
@@ -1425,36 +849,27 @@ class LoadUpper<string opstr, RegisterOperand RO, Operand Imm>:
}
// Memory Load/Store
-class LoadMemory<string opstr, DAGOperand RO, DAGOperand MO,
- SDPatternOperator OpNode = null_frag,
- InstrItinClass Itin = NoItinerary,
- ComplexPattern Addr = addr> :
- InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
+class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
+ InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> :
+ InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(set RO:$rt, (OpNode Addr:$addr))], Itin, FrmI, opstr> {
let DecoderMethod = "DecodeMem";
let canFoldAsLoad = 1;
- string BaseOpcode = opstr;
let mayLoad = 1;
}
-class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
- InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> :
- LoadMemory<opstr, RO, mem, OpNode, Itin, Addr>;
-
class StoreMemory<string opstr, DAGOperand RO, DAGOperand MO,
SDPatternOperator OpNode = null_frag,
InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> :
InstSE<(outs), (ins RO:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(OpNode RO:$rt, Addr:$addr)], Itin, FrmI, opstr> {
let DecoderMethod = "DecodeMem";
- string BaseOpcode = opstr;
let mayStore = 1;
}
class Store<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
- InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr,
- DAGOperand MO = mem> :
- StoreMemory<opstr, RO, MO, OpNode, Itin, Addr>;
+ InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> :
+ StoreMemory<opstr, RO, mem, OpNode, Itin, Addr>;
// Load/Store Left/Right
let canFoldAsLoad = 1 in
@@ -1465,7 +880,6 @@ class LoadLeftRight<string opstr, SDNode OpNode, RegisterOperand RO,
[(set RO:$rt, (OpNode addr:$addr, RO:$src))], Itin, FrmI> {
let DecoderMethod = "DecodeMem";
string Constraints = "$src = $rt";
- let BaseOpcode = opstr;
}
class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO,
@@ -1473,14 +887,12 @@ class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO,
InstSE<(outs), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(OpNode RO:$rt, addr:$addr)], Itin, FrmI> {
let DecoderMethod = "DecodeMem";
- let BaseOpcode = opstr;
}
// COP2 Load/Store
class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin,
SDPatternOperator OpNode= null_frag> :
- InstSE<(outs RC:$rt), (ins mem_simm16:$addr),
- !strconcat(opstr, "\t$rt, $addr"),
+ InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> {
let DecoderMethod = "DecodeFMem2";
let mayLoad = 1;
@@ -1488,8 +900,7 @@ class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin,
class SW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin,
SDPatternOperator OpNode= null_frag> :
- InstSE<(outs), (ins RC:$rt, mem_simm16:$addr),
- !strconcat(opstr, "\t$rt, $addr"),
+ InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> {
let DecoderMethod = "DecodeFMem2";
let mayStore = 1;
@@ -1514,49 +925,27 @@ class SW_FT3<string opstr, RegisterOperand RC, InstrItinClass Itin,
// Conditional Branch
class CBranch<string opstr, DAGOperand opnd, PatFrag cond_op,
- RegisterOperand RO> :
+ RegisterOperand RO, bit DelaySlot = 1> :
InstSE<(outs), (ins RO:$rs, RO:$rt, opnd:$offset),
!strconcat(opstr, "\t$rs, $rt, $offset"),
[(brcond (i32 (cond_op RO:$rs, RO:$rt)), bb:$offset)], II_BCC,
FrmI, opstr> {
let isBranch = 1;
let isTerminator = 1;
- let hasDelaySlot = 1;
+ let hasDelaySlot = DelaySlot;
let Defs = [AT];
- bit isCTI = 1;
-}
-
-class CBranchLikely<string opstr, DAGOperand opnd, RegisterOperand RO> :
- InstSE<(outs), (ins RO:$rs, RO:$rt, opnd:$offset),
- !strconcat(opstr, "\t$rs, $rt, $offset"), [], II_BCC, FrmI, opstr> {
- let isBranch = 1;
- let isTerminator = 1;
- let hasDelaySlot = 1;
- let Defs = [AT];
- bit isCTI = 1;
}
class CBranchZero<string opstr, DAGOperand opnd, PatFrag cond_op,
- RegisterOperand RO> :
+ RegisterOperand RO, bit DelaySlot = 1> :
InstSE<(outs), (ins RO:$rs, opnd:$offset),
!strconcat(opstr, "\t$rs, $offset"),
[(brcond (i32 (cond_op RO:$rs, 0)), bb:$offset)], II_BCCZ,
FrmI, opstr> {
let isBranch = 1;
let isTerminator = 1;
- let hasDelaySlot = 1;
- let Defs = [AT];
- bit isCTI = 1;
-}
-
-class CBranchZeroLikely<string opstr, DAGOperand opnd, RegisterOperand RO> :
- InstSE<(outs), (ins RO:$rs, opnd:$offset),
- !strconcat(opstr, "\t$rs, $offset"), [], II_BCCZ, FrmI, opstr> {
- let isBranch = 1;
- let isTerminator = 1;
- let hasDelaySlot = 1;
+ let hasDelaySlot = DelaySlot;
let Defs = [AT];
- bit isCTI = 1;
}
// SetCC
@@ -1583,24 +972,22 @@ class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator,
let hasDelaySlot = 1;
let DecoderMethod = "DecodeJumpTarget";
let Defs = [AT];
- bit isCTI = 1;
}
// Unconditional branch
-class UncondBranch<Instruction BEQInst, DAGOperand opnd> :
+class UncondBranch<Instruction BEQInst> :
PseudoSE<(outs), (ins brtarget:$offset), [(br bb:$offset)], II_B>,
- PseudoInstExpansion<(BEQInst ZERO, ZERO, opnd:$offset)> {
+ PseudoInstExpansion<(BEQInst ZERO, ZERO, brtarget:$offset)> {
let isBranch = 1;
let isTerminator = 1;
let isBarrier = 1;
let hasDelaySlot = 1;
let AdditionalPredicates = [RelocPIC];
let Defs = [AT];
- bit isCTI = 1;
}
// Base class for indirect branch and return instruction classes.
-let isTerminator=1, isBarrier=1, hasDelaySlot = 1, isCTI = 1 in
+let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in
class JumpFR<string opstr, RegisterOperand RO,
SDPatternOperator operator = null_frag>:
InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], II_JR,
@@ -1613,7 +1000,7 @@ class IndirectBranch<string opstr, RegisterOperand RO> : JumpFR<opstr, RO> {
}
// Jump and Link (Call)
-let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in {
+let isCall=1, hasDelaySlot=1, Defs = [RA] in {
class JumpLink<string opstr, DAGOperand opnd> :
InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"),
[(MipsJmpLink tglobaladdr:$target)], II_JAL, FrmJ, opstr> {
@@ -1623,101 +1010,89 @@ let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in {
class JumpLinkRegPseudo<RegisterOperand RO, Instruction JALRInst,
Register RetReg, RegisterOperand ResRO = RO>:
PseudoSE<(outs), (ins RO:$rs), [(MipsJmpLink RO:$rs)], II_JALR>,
- PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)> {
- let hasPostISelHook = 1;
- }
+ PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)>;
class JumpLinkReg<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
- [], II_JALR, FrmR, opstr> {
- let hasPostISelHook = 1;
- }
+ [], II_JALR, FrmR, opstr>;
class BGEZAL_FT<string opstr, DAGOperand opnd,
- RegisterOperand RO> :
+ RegisterOperand RO, bit DelaySlot = 1> :
InstSE<(outs), (ins RO:$rs, opnd:$offset),
!strconcat(opstr, "\t$rs, $offset"), [], II_BCCZAL, FrmI, opstr> {
- let hasDelaySlot = 1;
+ let hasDelaySlot = DelaySlot;
}
}
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1,
- hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in {
- class TailCall<Instruction JumpInst, DAGOperand Opnd> :
+ hasExtraSrcRegAllocReq = 1, Defs = [AT] in {
+ class TailCall<Instruction JumpInst> :
PseudoSE<(outs), (ins calltarget:$target), [], II_J>,
- PseudoInstExpansion<(JumpInst Opnd:$target)>;
+ PseudoInstExpansion<(JumpInst jmptarget:$target)>;
- class TailCallReg<Instruction JumpInst, RegisterOperand RO> :
+ class TailCallReg<RegisterOperand RO, Instruction JRInst,
+ RegisterOperand ResRO = RO> :
PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>,
- PseudoInstExpansion<(JumpInst RO:$rs)> {
- let hasPostISelHook = 1;
- }
+ PseudoInstExpansion<(JRInst ResRO:$rs)>;
}
-class BAL_BR_Pseudo<Instruction RealInst, DAGOperand opnd> :
- PseudoSE<(outs), (ins opnd:$offset), [], II_BCCZAL>,
- PseudoInstExpansion<(RealInst ZERO, opnd:$offset)> {
+class BAL_BR_Pseudo<Instruction RealInst> :
+ PseudoSE<(outs), (ins brtarget:$offset), [], II_BCCZAL>,
+ PseudoInstExpansion<(RealInst ZERO, brtarget:$offset)> {
let isBranch = 1;
let isTerminator = 1;
let isBarrier = 1;
let hasDelaySlot = 1;
let Defs = [RA];
- bit isCTI = 1;
}
-let isCTI = 1 in {
// Syscall
-class SYS_FT<string opstr, Operand ImmOp, InstrItinClass itin = NoItinerary> :
- InstSE<(outs), (ins ImmOp:$code_),
- !strconcat(opstr, "\t$code_"), [], itin, FrmI, opstr>;
+class SYS_FT<string opstr> :
+ InstSE<(outs), (ins uimm20:$code_),
+ !strconcat(opstr, "\t$code_"), [], NoItinerary, FrmI, opstr>;
// Break
class BRK_FT<string opstr> :
InstSE<(outs), (ins uimm10:$code_1, uimm10:$code_2),
- !strconcat(opstr, "\t$code_1, $code_2"), [], II_BREAK,
+ !strconcat(opstr, "\t$code_1, $code_2"), [], NoItinerary,
FrmOther, opstr>;
// (D)Eret
-class ER_FT<string opstr, InstrItinClass itin = NoItinerary> :
+class ER_FT<string opstr> :
InstSE<(outs), (ins),
- opstr, [], itin, FrmOther, opstr>;
-
-// Wait
-class WAIT_FT<string opstr> :
- InstSE<(outs), (ins), opstr, [], II_WAIT, FrmOther, opstr>;
-}
+ opstr, [], NoItinerary, FrmOther, opstr>;
// Interrupts
-class DEI_FT<string opstr, RegisterOperand RO,
- InstrItinClass itin = NoItinerary> :
+class DEI_FT<string opstr, RegisterOperand RO> :
InstSE<(outs RO:$rt), (ins),
- !strconcat(opstr, "\t$rt"), [], itin, FrmOther, opstr>;
+ !strconcat(opstr, "\t$rt"), [], NoItinerary, FrmOther, opstr>;
+
+// Wait
+class WAIT_FT<string opstr> :
+ InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther, opstr>;
// Sync
let hasSideEffects = 1 in
class SYNC_FT<string opstr> :
- InstSE<(outs), (ins uimm5:$stype), "sync $stype",
- [(MipsSync immZExt5:$stype)], II_SYNC, FrmOther, opstr>;
+ InstSE<(outs), (ins i32imm:$stype), "sync $stype", [(MipsSync imm:$stype)],
+ NoItinerary, FrmOther, opstr>;
-class SYNCI_FT<string opstr, DAGOperand MO> :
- InstSE<(outs), (ins MO:$addr), !strconcat(opstr, "\t$addr"), [],
- II_SYNCI, FrmOther, opstr> {
+class SYNCI_FT<string opstr> :
+ InstSE<(outs), (ins mem_simm16:$addr), !strconcat(opstr, "\t$addr"), [],
+ NoItinerary, FrmOther, opstr> {
let hasSideEffects = 1;
let DecoderMethod = "DecodeSyncI";
}
-let hasSideEffects = 1, isCTI = 1 in {
-class TEQ_FT<string opstr, RegisterOperand RO, Operand ImmOp,
- InstrItinClass itin = NoItinerary> :
- InstSE<(outs), (ins RO:$rs, RO:$rt, ImmOp:$code_),
- !strconcat(opstr, "\t$rs, $rt, $code_"), [], itin, FrmI, opstr>;
-
-class TEQI_FT<string opstr, RegisterOperand RO,
- InstrItinClass itin = NoItinerary> :
- InstSE<(outs), (ins RO:$rs, simm16:$imm16),
- !strconcat(opstr, "\t$rs, $imm16"), [], itin, FrmOther, opstr>;
-}
-
+let hasSideEffects = 1 in
+class TEQ_FT<string opstr, RegisterOperand RO> :
+ InstSE<(outs), (ins RO:$rs, RO:$rt, uimm16:$code_),
+ !strconcat(opstr, "\t$rs, $rt, $code_"), [], NoItinerary,
+ FrmI, opstr>;
+
+class TEQI_FT<string opstr, RegisterOperand RO> :
+ InstSE<(outs), (ins RO:$rs, uimm16:$imm16),
+ !strconcat(opstr, "\t$rs, $imm16"), [], NoItinerary, FrmOther, opstr>;
// Mul, Div
class Mult<string opstr, InstrItinClass itin, RegisterOperand RO,
list<Register> DefRegs> :
@@ -1772,7 +1147,6 @@ class MoveFromLOHI<string opstr, RegisterOperand RO, Register UseReg>:
FrmR, opstr> {
let Uses = [UseReg];
let hasSideEffects = 0;
- let isMoveReg = 1;
}
class PseudoMTLOHI<RegisterClass DstRC, RegisterClass SrcRC>
@@ -1785,28 +1159,24 @@ class MoveToLOHI<string opstr, RegisterOperand RO, list<Register> DefRegs>:
FrmR, opstr> {
let Defs = DefRegs;
let hasSideEffects = 0;
- let isMoveReg = 1;
}
class EffectiveAddress<string opstr, RegisterOperand RO> :
InstSE<(outs RO:$rt), (ins mem_ea:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(set RO:$rt, addr:$addr)], II_ADDIU, FrmI,
+ [(set RO:$rt, addr:$addr)], NoItinerary, FrmI,
!strconcat(opstr, "_lea")> {
let isCodeGenOnly = 1;
- let hasNoSchedulingInfo = 1;
let DecoderMethod = "DecodeMem";
}
// Count Leading Ones/Zeros in Word
-class CountLeading0<string opstr, RegisterOperand RO,
- InstrItinClass itin = NoItinerary>:
+class CountLeading0<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
- [(set RO:$rd, (ctlz RO:$rs))], itin, FrmR, opstr>;
+ [(set RO:$rd, (ctlz RO:$rs))], II_CLZ, FrmR, opstr>;
-class CountLeading1<string opstr, RegisterOperand RO,
- InstrItinClass itin = NoItinerary>:
+class CountLeading1<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
- [(set RO:$rd, (ctlz (not RO:$rs)))], itin, FrmR, opstr>;
+ [(set RO:$rd, (ctlz (not RO:$rs)))], II_CLO, FrmR, opstr>;
// Sign Extend in Register.
class SignExtInReg<string opstr, ValueType vt, RegisterOperand RO,
@@ -1824,26 +1194,23 @@ class SubwordSwap<string opstr, RegisterOperand RO,
// Read Hardware
class ReadHardware<RegisterOperand CPURegOperand, RegisterOperand RO> :
- InstSE<(outs CPURegOperand:$rt), (ins RO:$rd, uimm8:$sel),
- "rdhwr\t$rt, $rd, $sel", [], II_RDHWR, FrmR, "rdhwr">;
+ InstSE<(outs CPURegOperand:$rt), (ins RO:$rd), "rdhwr\t$rt, $rd", [],
+ II_RDHWR, FrmR, "rdhwr">;
// Ext and Ins
class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd,
- Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm,
- SDPatternOperator Op = null_frag> :
+ Operand SizeOpnd, SDPatternOperator Op = null_frag> :
InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size),
- !strconcat(opstr, "\t$rt, $rs, $pos, $size"),
- [(set RO:$rt, (Op RO:$rs, PosImm:$pos, SizeImm:$size))], II_EXT,
- FrmR, opstr>;
+ !strconcat(opstr, " $rt, $rs, $pos, $size"),
+ [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], II_EXT,
+ FrmR, opstr>, ISA_MIPS32R2;
-// 'ins' and its' 64 bit variants are matched by C++ code.
class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd,
- Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm>:
- InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size, RO:$src),
- !strconcat(opstr, "\t$rt, $rs, $pos, $size"),
- [(set RO:$rt, (null_frag RO:$rs, PosImm:$pos, SizeImm:$size,
- RO:$src))],
- II_INS, FrmR, opstr> {
+ SDPatternOperator Op = null_frag>:
+ InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ins:$size, RO:$src),
+ !strconcat(opstr, " $rt, $rs, $pos, $size"),
+ [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))],
+ II_INS, FrmR, opstr>, ISA_MIPS32R2 {
let Constraints = "$src = $rt";
}
@@ -1852,73 +1219,40 @@ class Atomic2Ops<PatFrag Op, RegisterClass DRC> :
PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$incr),
[(set DRC:$dst, (Op iPTR:$ptr, DRC:$incr))]>;
-class Atomic2OpsPostRA<RegisterClass RC> :
- PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr), []> {
- let mayLoad = 1;
- let mayStore = 1;
-}
-
-class Atomic2OpsSubwordPostRA<RegisterClass RC> :
- PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr, RC:$mask, RC:$mask2,
- RC:$shiftamnt), []>;
-
// Atomic Compare & Swap.
-// Atomic compare and swap is lowered into two stages. The first stage happens
-// during ISelLowering, which produces the PostRA version of this instruction.
class AtomicCmpSwap<PatFrag Op, RegisterClass DRC> :
PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$cmp, DRC:$swap),
[(set DRC:$dst, (Op iPTR:$ptr, DRC:$cmp, DRC:$swap))]>;
-class AtomicCmpSwapPostRA<RegisterClass RC> :
- PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$cmp, RC:$swap), []> {
- let mayLoad = 1;
- let mayStore = 1;
-}
-
-class AtomicCmpSwapSubwordPostRA<RegisterClass RC> :
- PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$mask, RC:$ShiftCmpVal,
- RC:$mask2, RC:$ShiftNewVal, RC:$ShiftAmt), []> {
- let mayLoad = 1;
- let mayStore = 1;
-}
-
-
-class LLBase<string opstr, RegisterOperand RO, DAGOperand MO = mem> :
- InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [], II_LL, FrmI, opstr> {
+class LLBase<string opstr, RegisterOperand RO> :
+ InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
+ [], NoItinerary, FrmI> {
let DecoderMethod = "DecodeMem";
let mayLoad = 1;
}
class SCBase<string opstr, RegisterOperand RO> :
InstSE<(outs RO:$dst), (ins RO:$rt, mem:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], II_SC, FrmI> {
+ !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> {
let DecoderMethod = "DecodeMem";
let mayStore = 1;
let Constraints = "$rt = $dst";
}
-class MFC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD,
- InstrItinClass itin> :
- InstSE<(outs RO:$rt), (ins RD:$rd, uimm3:$sel),
- !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR> {
- let BaseOpcode = asmstr;
-}
+class MFC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD> :
+ InstSE<(outs RO:$rt), (ins RD:$rd, uimm16:$sel),
+ !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>;
-class MTC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD,
- InstrItinClass itin> :
- InstSE<(outs RO:$rd), (ins RD:$rt, uimm3:$sel),
- !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR> {
- let BaseOpcode = asmstr;
-}
+class MTC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD> :
+ InstSE<(outs RO:$rd), (ins RD:$rt, uimm16:$sel),
+ !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>;
class TrapBase<Instruction RealInst>
- : PseudoSE<(outs), (ins), [(trap)], II_TRAP>,
+ : PseudoSE<(outs), (ins), [(trap)], NoItinerary>,
PseudoInstExpansion<(RealInst 0, 0)> {
let isBarrier = 1;
let isTerminator = 1;
let isCodeGenOnly = 1;
- let isCTI = 1;
}
//===----------------------------------------------------------------------===//
@@ -1926,17 +1260,15 @@ class TrapBase<Instruction RealInst>
//===----------------------------------------------------------------------===//
// Return RA.
-let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, isCTI=1 in {
- let hasDelaySlot=1 in
- def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>;
+let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in
+def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>;
- let hasSideEffects=1 in
- def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>;
-}
+let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, hasSideEffects=1 in
+def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>;
let Defs = [SP], Uses = [SP], hasSideEffects = 1 in {
-def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
- [(callseq_start timm:$amt1, timm:$amt2)]>;
+def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt),
+ [(callseq_start timm:$amt)]>;
def ADJCALLSTACKUP : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
[(callseq_end timm:$amt1, timm:$amt2)]>;
}
@@ -1968,38 +1300,10 @@ let usesCustomInserter = 1 in {
def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap<atomic_cmp_swap_8, GPR32>;
def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap<atomic_cmp_swap_16, GPR32>;
def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap<atomic_cmp_swap_32, GPR32>;
-
}
-def ATOMIC_LOAD_ADD_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_ADD_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_ADD_I32_POSTRA : Atomic2OpsPostRA<GPR32>;
-def ATOMIC_LOAD_SUB_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_SUB_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_SUB_I32_POSTRA : Atomic2OpsPostRA<GPR32>;
-def ATOMIC_LOAD_AND_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_AND_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_AND_I32_POSTRA : Atomic2OpsPostRA<GPR32>;
-def ATOMIC_LOAD_OR_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_OR_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_OR_I32_POSTRA : Atomic2OpsPostRA<GPR32>;
-def ATOMIC_LOAD_XOR_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_XOR_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_XOR_I32_POSTRA : Atomic2OpsPostRA<GPR32>;
-def ATOMIC_LOAD_NAND_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_NAND_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_LOAD_NAND_I32_POSTRA : Atomic2OpsPostRA<GPR32>;
-
-def ATOMIC_SWAP_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_SWAP_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>;
-def ATOMIC_SWAP_I32_POSTRA : Atomic2OpsPostRA<GPR32>;
-
-def ATOMIC_CMP_SWAP_I8_POSTRA : AtomicCmpSwapSubwordPostRA<GPR32>;
-def ATOMIC_CMP_SWAP_I16_POSTRA : AtomicCmpSwapSubwordPostRA<GPR32>;
-def ATOMIC_CMP_SWAP_I32_POSTRA : AtomicCmpSwapPostRA<GPR32>;
-
/// Pseudo instructions for loading and storing accumulator registers.
-let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in {
+let isPseudo = 1, isCodeGenOnly = 1 in {
def LOAD_ACC64 : Load<"", ACC64>;
def STORE_ACC64 : Store<"", ACC64>;
}
@@ -2008,19 +1312,13 @@ let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in {
// branches. See the comment in file MipsLongBranch.cpp for detailed
// explanation.
-// Expands to: lui $dst, %highest/%higher/%hi/%lo($tgt - $baltgt)
+// Expands to: lui $dst, %hi($tgt - $baltgt)
def LONG_BRANCH_LUi : PseudoSE<(outs GPR32Opnd:$dst),
(ins brtarget:$tgt, brtarget:$baltgt), []>;
-// Expands to: lui $dst, highest/%higher/%hi/%lo($tgt)
-def LONG_BRANCH_LUi2Op : PseudoSE<(outs GPR32Opnd:$dst),
- (ins brtarget:$tgt), []>;
-// Expands to: addiu $dst, $src, %highest/%higher/%hi/%lo($tgt - $baltgt)
+// Expands to: addiu $dst, $src, %lo($tgt - $baltgt)
def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst),
(ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>;
-// Expands to: addiu $dst, $src, %highest/%higher/%hi/%lo($tgt)
-def LONG_BRANCH_ADDiu2Op : PseudoSE<(outs GPR32Opnd:$dst),
- (ins GPR32Opnd:$src, brtarget:$tgt), []>;
//===----------------------------------------------------------------------===//
// Instruction definition
@@ -2031,273 +1329,242 @@ def LONG_BRANCH_ADDiu2Op : PseudoSE<(outs GPR32Opnd:$dst),
/// Arithmetic Instructions (ALU Immediate)
let AdditionalPredicates = [NotInMicroMips] in {
- def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16_relaxed, GPR32Opnd,
- II_ADDIU, immSExt16, add>,
- ADDI_FM<0x9>, IsAsCheapAsAMove, ISA_MIPS1;
-
- def ANDi : MMRel, StdMMR6Rel,
- ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>,
- ADDI_FM<0xc>, ISA_MIPS1;
- def ORi : MMRel, StdMMR6Rel,
- ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>,
- ADDI_FM<0xd>, ISA_MIPS1;
- def XORi : MMRel, StdMMR6Rel,
- ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>,
- ADDI_FM<0xe>, ISA_MIPS1;
- def ADDi : MMRel, ArithLogicI<"addi", simm16_relaxed, GPR32Opnd, II_ADDI>,
- ADDI_FM<0x8>, ISA_MIPS1_NOT_32R6_64R6;
- def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>,
- SLTI_FM<0xa>, ISA_MIPS1;
- def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>,
- SLTI_FM<0xb>, ISA_MIPS1;
-
- def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM,
- ISA_MIPS1;
-
- /// Arithmetic Instructions (3-Operand, R-Type)
- def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>,
- ADD_FM<0, 0x21>, ISA_MIPS1;
- def SUBu : MMRel, StdMMR6Rel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>,
- ADD_FM<0, 0x23>, ISA_MIPS1;
-
- let Defs = [HI0, LO0] in
- def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>,
- ADD_FM<0x1c, 2>, ISA_MIPS32_NOT_32R6_64R6;
-
- def ADD : MMRel, StdMMR6Rel, ArithLogicR<"add", GPR32Opnd, 1, II_ADD>,
- ADD_FM<0, 0x20>, ISA_MIPS1;
- def SUB : MMRel, StdMMR6Rel, ArithLogicR<"sub", GPR32Opnd, 0, II_SUB>,
- ADD_FM<0, 0x22>, ISA_MIPS1;
-
- def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>,
- ISA_MIPS1;
- def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>,
- ISA_MIPS1;
- def AND : MMRel, StdMMR6Rel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>,
- ADD_FM<0, 0x24>, ISA_MIPS1;
- def OR : MMRel, StdMMR6Rel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>,
- ADD_FM<0, 0x25>, ISA_MIPS1;
- def XOR : MMRel, StdMMR6Rel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>,
- ADD_FM<0, 0x26>, ISA_MIPS1;
- def NOR : MMRel, StdMMR6Rel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>,
- ISA_MIPS1;
+def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16, GPR32Opnd,
+ II_ADDIU, immSExt16, add>,
+ ADDI_FM<0x9>, IsAsCheapAsAMove;
+}
+def ADDi : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd>, ADDI_FM<0x8>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>,
+ SLTI_FM<0xa>;
+def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>,
+ SLTI_FM<0xb>;
+let AdditionalPredicates = [NotInMicroMips] in {
+def ANDi : MMRel, StdMMR6Rel,
+ ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>,
+ ADDI_FM<0xc>;
+}
+def ORi : MMRel, StdMMR6Rel,
+ ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>,
+ ADDI_FM<0xd>;
+def XORi : MMRel, StdMMR6Rel,
+ ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>,
+ ADDI_FM<0xe>;
+def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16>, LUI_FM;
+let AdditionalPredicates = [NotInMicroMips] in {
+/// Arithmetic Instructions (3-Operand, R-Type)
+def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>,
+ ADD_FM<0, 0x21>;
+def SUBu : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>,
+ ADD_FM<0, 0x23>;
+}
+let Defs = [HI0, LO0] in
+def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>,
+ ADD_FM<0x1c, 2>, ISA_MIPS32_NOT_32R6_64R6;
+def ADD : MMRel, StdMMR6Rel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>;
+def SUB : MMRel, ArithLogicR<"sub", GPR32Opnd>, ADD_FM<0, 0x22>;
+def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>;
+def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>;
+let AdditionalPredicates = [NotInMicroMips] in {
+def AND : MMRel, StdMMR6Rel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>,
+ ADD_FM<0, 0x24>;
+def OR : MMRel, StdMMR6Rel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>,
+ ADD_FM<0, 0x25>;
+def XOR : MMRel, StdMMR6Rel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>,
+ ADD_FM<0, 0x26>;
}
+def NOR : MMRel, StdMMR6Rel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>;
+/// Shift Instructions
let AdditionalPredicates = [NotInMicroMips] in {
- /// Shift Instructions
- def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, shl,
- immZExt5>, SRA_FM<0, 0>, ISA_MIPS1;
- def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, srl,
- immZExt5>, SRA_FM<2, 0>, ISA_MIPS1;
- def SRA : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, sra,
- immZExt5>, SRA_FM<3, 0>, ISA_MIPS1;
- def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, shl>,
- SRLV_FM<4, 0>, ISA_MIPS1;
- def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, srl>,
- SRLV_FM<6, 0>, ISA_MIPS1;
- def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>,
- SRLV_FM<7, 0>, ISA_MIPS1;
-
- // Rotate Instructions
- def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr,
- immZExt5>,
- SRA_FM<2, 1>, ISA_MIPS32R2;
- def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>,
- SRLV_FM<6, 1>, ISA_MIPS32R2;
-}
+def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, shl,
+ immZExt5>, SRA_FM<0, 0>;
+def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, srl,
+ immZExt5>, SRA_FM<2, 0>;
+}
+def SRA : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, sra,
+ immZExt5>, SRA_FM<3, 0>;
+def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, shl>,
+ SRLV_FM<4, 0>;
+def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, srl>,
+ SRLV_FM<6, 0>;
+def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>,
+ SRLV_FM<7, 0>;
+
+// Rotate Instructions
+def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr,
+ immZExt5>,
+ SRA_FM<2, 1>, ISA_MIPS32R2;
+def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>,
+ SRLV_FM<6, 1>, ISA_MIPS32R2;
/// Load and Store Instructions
/// aligned
+def LB : Load<"lb", GPR32Opnd, sextloadi8, II_LB>, MMRel, LW_FM<0x20>;
+def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel,
+ LW_FM<0x24>;
+def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel,
+ LW_FM<0x21>;
+def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>;
+let AdditionalPredicates = [NotInMicroMips] in {
+def LW : StdMMR6Rel, Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel,
+ LW_FM<0x23>;
+}
+def SB : StdMMR6Rel, Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel,
+ LW_FM<0x28>;
+def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>;
let AdditionalPredicates = [NotInMicroMips] in {
- def LB : LoadMemory<"lb", GPR32Opnd, mem_simmptr, sextloadi8, II_LB>, MMRel,
- LW_FM<0x20>, ISA_MIPS1;
- def LBu : LoadMemory<"lbu", GPR32Opnd, mem_simmptr, zextloadi8, II_LBU,
- addrDefault>, MMRel, LW_FM<0x24>, ISA_MIPS1;
- def LH : LoadMemory<"lh", GPR32Opnd, mem_simmptr, sextloadi16, II_LH,
- addrDefault>, MMRel, LW_FM<0x21>, ISA_MIPS1;
- def LHu : LoadMemory<"lhu", GPR32Opnd, mem_simmptr, zextloadi16, II_LHU>,
- MMRel, LW_FM<0x25>, ISA_MIPS1;
- def LW : StdMMR6Rel, Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel,
- LW_FM<0x23>, ISA_MIPS1;
- def SB : StdMMR6Rel, Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel,
- LW_FM<0x28>, ISA_MIPS1;
- def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>,
- ISA_MIPS1;
- def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>, ISA_MIPS1;
+def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>;
}
/// load/store left/right
-let AdditionalPredicates = [NotInMicroMips] in {
-def LWL : MMRel, LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>,
+let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
+ AdditionalPredicates = [NotInMicroMips] in {
+def LWL : LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>,
ISA_MIPS1_NOT_32R6_64R6;
-def LWR : MMRel, LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>,
+def LWR : LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>,
ISA_MIPS1_NOT_32R6_64R6;
-def SWL : MMRel, StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>,
+def SWL : StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>,
ISA_MIPS1_NOT_32R6_64R6;
-def SWR : MMRel, StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>,
+def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>,
ISA_MIPS1_NOT_32R6_64R6;
+}
+let AdditionalPredicates = [NotInMicroMips] in {
// COP2 Memory Instructions
-def LWC2 : StdMMR6Rel, LW_FT2<"lwc2", COP2Opnd, II_LWC2, load>, LW_FM<0x32>,
+def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def SWC2 : SW_FT2<"swc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3a>,
ISA_MIPS1_NOT_32R6_64R6;
-def SWC2 : StdMMR6Rel, SW_FT2<"swc2", COP2Opnd, II_SWC2, store>,
- LW_FM<0x3a>, ISA_MIPS1_NOT_32R6_64R6;
-def LDC2 : StdMMR6Rel, LW_FT2<"ldc2", COP2Opnd, II_LDC2, load>, LW_FM<0x36>,
+def LDC2 : LW_FT2<"ldc2", COP2Opnd, NoItinerary, load>, LW_FM<0x36>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def SDC2 : SW_FT2<"sdc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3e>,
ISA_MIPS2_NOT_32R6_64R6;
-def SDC2 : StdMMR6Rel, SW_FT2<"sdc2", COP2Opnd, II_SDC2, store>,
- LW_FM<0x3e>, ISA_MIPS2_NOT_32R6_64R6;
// COP3 Memory Instructions
let DecoderNamespace = "COP3_" in {
- def LWC3 : LW_FT3<"lwc3", COP3Opnd, II_LWC3, load>, LW_FM<0x33>,
- ISA_MIPS1_NOT_32R6_64R6, NOT_ASE_CNMIPS;
- def SWC3 : SW_FT3<"swc3", COP3Opnd, II_SWC3, store>, LW_FM<0x3b>,
- ISA_MIPS1_NOT_32R6_64R6, NOT_ASE_CNMIPS;
- def LDC3 : LW_FT3<"ldc3", COP3Opnd, II_LDC3, load>, LW_FM<0x37>,
- ISA_MIPS2, NOT_ASE_CNMIPS;
- def SDC3 : SW_FT3<"sdc3", COP3Opnd, II_SDC3, store>, LW_FM<0x3f>,
- ISA_MIPS2, NOT_ASE_CNMIPS;
+ def LWC3 : LW_FT3<"lwc3", COP3Opnd, NoItinerary, load>, LW_FM<0x33>;
+ def SWC3 : SW_FT3<"swc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3b>;
+ def LDC3 : LW_FT3<"ldc3", COP3Opnd, NoItinerary, load>, LW_FM<0x37>,
+ ISA_MIPS2;
+ def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>,
+ ISA_MIPS2;
}
-
- def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS2;
- def SYNCI : MMRel, StdMMR6Rel, SYNCI_FT<"synci", mem_simm16>, SYNCI_FM,
- ISA_MIPS32R2;
}
-let AdditionalPredicates = [NotInMicroMips] in {
- def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd, uimm10, II_TEQ>, TEQ_FM<0x34>,
- ISA_MIPS2;
- def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd, uimm10, II_TGE>, TEQ_FM<0x30>,
- ISA_MIPS2;
- def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd, uimm10, II_TGEU>, TEQ_FM<0x31>,
- ISA_MIPS2;
- def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd, uimm10, II_TLT>, TEQ_FM<0x32>,
- ISA_MIPS2;
- def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd, uimm10, II_TLTU>, TEQ_FM<0x33>,
- ISA_MIPS2;
- def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd, uimm10, II_TNE>, TEQ_FM<0x36>,
- ISA_MIPS2;
-
- def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd, II_TEQI>, TEQI_FM<0xc>,
- ISA_MIPS2_NOT_32R6_64R6;
- def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd, II_TGEI>, TEQI_FM<0x8>,
- ISA_MIPS2_NOT_32R6_64R6;
- def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd, II_TGEIU>, TEQI_FM<0x9>,
- ISA_MIPS2_NOT_32R6_64R6;
- def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd, II_TLTI>, TEQI_FM<0xa>,
- ISA_MIPS2_NOT_32R6_64R6;
- def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd, II_TTLTIU>, TEQI_FM<0xb>,
- ISA_MIPS2_NOT_32R6_64R6;
- def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd, II_TNEI>, TEQI_FM<0xe>,
- ISA_MIPS2_NOT_32R6_64R6;
-}
+def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32;
+def SYNCI : MMRel, StdMMR6Rel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2;
let AdditionalPredicates = [NotInMicroMips] in {
- def BREAK : MMRel, StdMMR6Rel, BRK_FT<"break">, BRK_FM<0xd>, ISA_MIPS1;
- def SYSCALL : MMRel, SYS_FT<"syscall", uimm20, II_SYSCALL>, SYS_FM<0xc>,
- ISA_MIPS1;
- def TRAP : TrapBase<BREAK>, ISA_MIPS1;
- def SDBBP : MMRel, SYS_FT<"sdbbp", uimm20, II_SDBBP>, SDBBP_FM,
- ISA_MIPS32_NOT_32R6_64R6;
+ def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM<0x34>, ISA_MIPS2;
+ def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd>, TEQ_FM<0x30>, ISA_MIPS2;
+ def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd>, TEQ_FM<0x31>, ISA_MIPS2;
+ def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM<0x32>, ISA_MIPS2;
+ def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM<0x33>, ISA_MIPS2;
+ def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM<0x36>, ISA_MIPS2;
+}
- def ERET : MMRel, ER_FT<"eret", II_ERET>, ER_FM<0x18, 0x0>, INSN_MIPS3_32;
- def ERETNC : MMRel, ER_FT<"eretnc", II_ERETNC>, ER_FM<0x18, 0x1>,
- ISA_MIPS32R5;
- def DERET : MMRel, ER_FT<"deret", II_DERET>, ER_FM<0x1f, 0x0>, ISA_MIPS32;
+def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM<0xc>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM<0x8>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd>, TEQI_FM<0x9>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd>, TEQI_FM<0xa>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd>, TEQI_FM<0xb>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd>, TEQI_FM<0xe>,
+ ISA_MIPS2_NOT_32R6_64R6;
- def EI : MMRel, StdMMR6Rel, DEI_FT<"ei", GPR32Opnd, II_EI>, EI_FM<1>,
- ISA_MIPS32R2;
- def DI : MMRel, StdMMR6Rel, DEI_FT<"di", GPR32Opnd, II_DI>, EI_FM<0>,
- ISA_MIPS32R2;
+let AdditionalPredicates = [NotInMicroMips] in {
+def BREAK : MMRel, StdMMR6Rel, BRK_FT<"break">, BRK_FM<0xd>;
+}
+def SYSCALL : MMRel, SYS_FT<"syscall">, SYS_FM<0xc>;
+def TRAP : TrapBase<BREAK>;
+def SDBBP : MMRel, SYS_FT<"sdbbp">, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6;
- def WAIT : MMRel, StdMMR6Rel, WAIT_FT<"wait">, WAIT_FM, INSN_MIPS3_32;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18, 0x0>, INSN_MIPS3_32;
+ def ERETNC : MMRel, ER_FT<"eretnc">, ER_FM<0x18, 0x1>, ISA_MIPS32R5;
+ def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f, 0x0>, ISA_MIPS32;
}
let AdditionalPredicates = [NotInMicroMips] in {
+ def EI : MMRel, StdMMR6Rel, DEI_FT<"ei", GPR32Opnd>, EI_FM<1>, ISA_MIPS32R2;
+ def DI : MMRel, StdMMR6Rel, DEI_FT<"di", GPR32Opnd>, EI_FM<0>, ISA_MIPS32R2;
+}
+
+let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
+ AdditionalPredicates = [NotInMicroMips] in {
+def WAIT : WAIT_FT<"wait">, WAIT_FM;
+
/// Load-linked, Store-conditional
-def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_32, ISA_MIPS2_NOT_32R6_64R6;
-def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_32, ISA_MIPS2_NOT_32R6_64R6;
+def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2_NOT_32R6_64R6;
+def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2_NOT_32R6_64R6;
}
+
/// Jump and Branch Instructions
-let AdditionalPredicates = [NotInMicroMips, RelocNotPIC] in
def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>,
- IsBranch, ISA_MIPS1;
-
-let AdditionalPredicates = [NotInMicroMips] in {
-def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>, ISA_MIPS1_NOT_32R6_64R6;
-def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>,
- ISA_MIPS1;
-def BEQL : MMRel, CBranchLikely<"beql", brtarget, GPR32Opnd>,
+ AdditionalRequires<[RelocStatic]>, IsBranch;
+def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>, ISA_MIPS1_NOT_32R6_64R6;
+def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>;
+def BEQL : MMRel, CBranch<"beql", brtarget, seteq, GPR32Opnd, 0>,
BEQ_FM<20>, ISA_MIPS2_NOT_32R6_64R6;
-def BNE : MMRel, CBranch<"bne", brtarget, setne, GPR32Opnd>, BEQ_FM<5>,
- ISA_MIPS1;
-def BNEL : MMRel, CBranchLikely<"bnel", brtarget, GPR32Opnd>,
+def BNE : MMRel, CBranch<"bne", brtarget, setne, GPR32Opnd>, BEQ_FM<5>;
+def BNEL : MMRel, CBranch<"bnel", brtarget, setne, GPR32Opnd, 0>,
BEQ_FM<21>, ISA_MIPS2_NOT_32R6_64R6;
def BGEZ : MMRel, CBranchZero<"bgez", brtarget, setge, GPR32Opnd>,
- BGEZ_FM<1, 1>, ISA_MIPS1;
-def BGEZL : MMRel, CBranchZeroLikely<"bgezl", brtarget, GPR32Opnd>,
+ BGEZ_FM<1, 1>;
+def BGEZL : MMRel, CBranchZero<"bgezl", brtarget, setge, GPR32Opnd, 0>,
BGEZ_FM<1, 3>, ISA_MIPS2_NOT_32R6_64R6;
def BGTZ : MMRel, CBranchZero<"bgtz", brtarget, setgt, GPR32Opnd>,
- BGEZ_FM<7, 0>, ISA_MIPS1;
-def BGTZL : MMRel, CBranchZeroLikely<"bgtzl", brtarget, GPR32Opnd>,
+ BGEZ_FM<7, 0>;
+def BGTZL : MMRel, CBranchZero<"bgtzl", brtarget, setgt, GPR32Opnd, 0>,
BGEZ_FM<23, 0>, ISA_MIPS2_NOT_32R6_64R6;
def BLEZ : MMRel, CBranchZero<"blez", brtarget, setle, GPR32Opnd>,
- BGEZ_FM<6, 0>, ISA_MIPS1;
-def BLEZL : MMRel, CBranchZeroLikely<"blezl", brtarget, GPR32Opnd>,
+ BGEZ_FM<6, 0>;
+def BLEZL : MMRel, CBranchZero<"blezl", brtarget, setle, GPR32Opnd, 0>,
BGEZ_FM<22, 0>, ISA_MIPS2_NOT_32R6_64R6;
def BLTZ : MMRel, CBranchZero<"bltz", brtarget, setlt, GPR32Opnd>,
- BGEZ_FM<1, 0>, ISA_MIPS1;
-def BLTZL : MMRel, CBranchZeroLikely<"bltzl", brtarget, GPR32Opnd>,
+ BGEZ_FM<1, 0>;
+def BLTZL : MMRel, CBranchZero<"bltzl", brtarget, setlt, GPR32Opnd, 0>,
BGEZ_FM<1, 2>, ISA_MIPS2_NOT_32R6_64R6;
-def B : UncondBranch<BEQ, brtarget>, ISA_MIPS1;
-
-def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>, ISA_MIPS1;
-
-}
+def B : UncondBranch<BEQ>;
-let AdditionalPredicates = [NotInMicroMips, NoIndirectJumpGuards] in {
- def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM, ISA_MIPS1;
- def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>, ISA_MIPS1;
+def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM;
+ def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>;
}
-let AdditionalPredicates = [NotInMicroMips] in {
- def JALX : MMRel, JumpLink<"jalx", calltarget>, FJ<0x1D>,
- ISA_MIPS32_NOT_32R6_64R6;
- def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>,
- ISA_MIPS1_NOT_32R6_64R6;
- def BGEZALL : MMRel, BGEZAL_FT<"bgezall", brtarget, GPR32Opnd>,
- BGEZAL_FM<0x13>, ISA_MIPS2_NOT_32R6_64R6;
- def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>,
- ISA_MIPS1_NOT_32R6_64R6;
- def BLTZALL : MMRel, BGEZAL_FT<"bltzall", brtarget, GPR32Opnd>,
- BGEZAL_FM<0x12>, ISA_MIPS2_NOT_32R6_64R6;
- def BAL_BR : BAL_BR_Pseudo<BGEZAL, brtarget>, ISA_MIPS1;
-}
-let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips] in {
- def TAILCALL : TailCall<J, jmptarget>, ISA_MIPS1;
-}
-let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
- NoIndirectJumpGuards] in
- def TAILCALLREG : TailCallReg<JR, GPR32Opnd>, ISA_MIPS1_NOT_32R6_64R6;
+def JALX : MMRel, JumpLink<"jalx", calltarget>, FJ<0x1D>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def BGEZALL : MMRel, BGEZAL_FT<"bgezall", brtarget, GPR32Opnd, 0>,
+ BGEZAL_FM<0x13>, ISA_MIPS2_NOT_32R6_64R6;
+def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def BLTZALL : MMRel, BGEZAL_FT<"bltzall", brtarget, GPR32Opnd, 0>,
+ BGEZAL_FM<0x12>, ISA_MIPS2_NOT_32R6_64R6;
+def BAL_BR : BAL_BR_Pseudo<BGEZAL>;
+def TAILCALL : TailCall<J>;
+def TAILCALL_R : TailCallReg<GPR32Opnd, JR>;
// Indirect branches are matched as PseudoIndirectBranch/PseudoIndirectBranch64
// then are expanded to JR, JR64, JALR, or JALR64 depending on the ISA.
-class PseudoIndirectBranchBase<Instruction JumpInst, RegisterOperand RO> :
+class PseudoIndirectBranchBase<RegisterOperand RO> :
MipsPseudo<(outs), (ins RO:$rs), [(brind RO:$rs)],
- II_IndirectBranchPseudo>,
- PseudoInstExpansion<(JumpInst RO:$rs)> {
+ II_IndirectBranchPseudo> {
let isTerminator=1;
let isBarrier=1;
let hasDelaySlot = 1;
let isBranch = 1;
let isIndirectBranch = 1;
- bit isCTI = 1;
}
-let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
- NoIndirectJumpGuards] in
- def PseudoIndirectBranch : PseudoIndirectBranchBase<JR, GPR32Opnd>,
- ISA_MIPS1_NOT_32R6_64R6;
+def PseudoIndirectBranch : PseudoIndirectBranchBase<GPR32Opnd>;
// Return instructions are matched as a RetRA instruction, then are expanded
// into PseudoReturn/PseudoReturn64 after register allocation. Finally,
@@ -2312,7 +1579,6 @@ class PseudoReturnBase<RegisterOperand RO> : MipsPseudo<(outs), (ins RO:$rs),
let isCodeGenOnly = 1;
let hasCtrlDep = 1;
let hasExtraSrcRegAllocReq = 1;
- bit isCTI = 1;
}
def PseudoReturn : PseudoReturnBase<GPR32Opnd>;
@@ -2330,7 +1596,7 @@ def SDT_MipsEHRET : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>;
def MIPSehret : SDNode<"MipsISD::EH_RETURN", SDT_MipsEHRET,
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
-let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in {
+let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in {
def MIPSeh_return32 : MipsPseudo<(outs), (ins GPR32:$spoff, GPR32:$dst),
[(MIPSehret GPR32:$spoff, GPR32:$dst)]>;
def MIPSeh_return64 : MipsPseudo<(outs), (ins GPR64:$spoff,
@@ -2339,61 +1605,63 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in
}
/// Multiply and Divide Instructions.
-let AdditionalPredicates = [NotInMicroMips] in {
- def MULT : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>,
- MULT_FM<0, 0x18>, ISA_MIPS1_NOT_32R6_64R6;
- def MULTu : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>,
- MULT_FM<0, 0x19>, ISA_MIPS1_NOT_32R6_64R6;
- def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>,
- MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6;
- def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>,
- MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6;
- def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>,
- ISA_MIPS1_NOT_32R6_64R6;
- def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>,
- ISA_MIPS1_NOT_32R6_64R6;
- def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>,
- ISA_MIPS1_NOT_32R6_64R6;
- def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>,
- ISA_MIPS1_NOT_32R6_64R6;
+def MULT : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>,
+ MULT_FM<0, 0x18>, ISA_MIPS1_NOT_32R6_64R6;
+def MULTu : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>,
+ MULT_FM<0, 0x19>, ISA_MIPS1_NOT_32R6_64R6;
+def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>,
+ MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6;
+def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>,
+ MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6;
+
+def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>,
+ ISA_MIPS1_NOT_32R6_64R6;
+let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
+ AdditionalPredicates = [NotInMicroMips] in {
+def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>,
+ ISA_MIPS1_NOT_32R6_64R6;
+}
- /// Sign Ext In Register Instructions.
- def SEB : MMRel, StdMMR6Rel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>,
- SEB_FM<0x10, 0x20>, ISA_MIPS32R2;
- def SEH : MMRel, StdMMR6Rel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>,
- SEB_FM<0x18, 0x20>, ISA_MIPS32R2;
+/// Sign Ext In Register Instructions.
+def SEB : MMRel, StdMMR6Rel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>,
+ SEB_FM<0x10, 0x20>, ISA_MIPS32R2;
+def SEH : MMRel, StdMMR6Rel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>,
+ SEB_FM<0x18, 0x20>, ISA_MIPS32R2;
- /// Count Leading
- def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd, II_CLZ>, CLO_FM<0x20>,
- ISA_MIPS32_NOT_32R6_64R6;
- def CLO : MMRel, CountLeading1<"clo", GPR32Opnd, II_CLO>, CLO_FM<0x21>,
- ISA_MIPS32_NOT_32R6_64R6;
+/// Count Leading
+def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>,
+ ISA_MIPS32_NOT_32R6_64R6;
+let AdditionalPredicates = [NotInMicroMips] in {
/// Word Swap Bytes Within Halfwords
def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd, II_WSBH>, SEB_FM<2, 0x20>,
ISA_MIPS32R2;
+}
- /// No operation.
- def NOP : PseudoSE<(outs), (ins), []>,
- PseudoInstExpansion<(SLL ZERO, ZERO, 0)>, ISA_MIPS1;
+/// No operation.
+def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>;
- // FrameIndexes are legalized when they are operands from load/store
- // instructions. The same not happens for stack address copies, so an
- // add op with mem ComplexPattern is used and the stack address copy
- // can be matched. It's similar to Sparc LEA_ADDRi
- let AdditionalPredicates = [NotInMicroMips] in
- def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>, ISA_MIPS1;
+// FrameIndexes are legalized when they are operands from load/store
+// instructions. The same not happens for stack address copies, so an
+// add op with mem ComplexPattern is used and the stack address copy
+// can be matched. It's similar to Sparc LEA_ADDRi
+def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>;
- // MADD*/MSUB*
- def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>,
- ISA_MIPS32_NOT_32R6_64R6;
- def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>,
- ISA_MIPS32_NOT_32R6_64R6;
- def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>,
- ISA_MIPS32_NOT_32R6_64R6;
- def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>,
- ISA_MIPS32_NOT_32R6_64R6;
-}
+// MADD*/MSUB*
+def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>,
+ ISA_MIPS32_NOT_32R6_64R6;
let AdditionalPredicates = [NotDSP] in {
def PseudoMULT : MultDivPseudo<MULT, ACC64, GPR32Opnd, MipsMult, II_MULT>,
@@ -2413,44 +1681,29 @@ def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu, II_MSUBU>,
ISA_MIPS32_NOT_32R6_64R6;
}
+def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV,
+ 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
+def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, II_DIVU,
+ 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
let AdditionalPredicates = [NotInMicroMips] in {
- def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV,
- 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
- def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, II_DIVU,
- 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
- def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM, ISA_MIPS1;
- // TODO: Add '0 < pos+size <= 32' constraint check to ext instruction
- def EXT : MMRel, StdMMR6Rel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1,
- immZExt5, immZExt5Plus1, MipsExt>,
- EXT_FM<0>, ISA_MIPS32R2;
- def INS : MMRel, StdMMR6Rel, InsBase<"ins", GPR32Opnd, uimm5,
- uimm5_inssize_plus1, immZExt5,
- immZExt5Plus1>,
- EXT_FM<4>, ISA_MIPS32R2;
+def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM;
}
+// TODO: Add '0 < pos+size <= 32' constraint check to ext instruction
+def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, MipsExt>,
+ EXT_FM<0>;
+def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, EXT_FM<4>;
+
/// Move Control Registers From/To CPU Registers
-let AdditionalPredicates = [NotInMicroMips] in {
- def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd, II_MTC0>,
- MFC3OP_FM<0x10, 4, 0>, ISA_MIPS1;
- def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd, II_MFC0>,
- MFC3OP_FM<0x10, 0, 0>, ISA_MIPS1;
- def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd, II_MFC2>,
- MFC3OP_FM<0x12, 0, 0>, ISA_MIPS1;
- def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd, II_MTC2>,
- MFC3OP_FM<0x12, 4, 0>, ISA_MIPS1;
-}
-
-class Barrier<string asmstr, InstrItinClass itin = NoItinerary> :
- InstSE<(outs), (ins), asmstr, [], itin, FrmOther, asmstr>;
-let AdditionalPredicates = [NotInMicroMips] in {
- def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop", II_SSNOP>, BARRIER_FM<1>,
- ISA_MIPS1;
- def EHB : MMRel, Barrier<"ehb", II_EHB>, BARRIER_FM<3>, ISA_MIPS1;
+def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32;
+def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd>, MFC3OP_FM<0x10, 4>, ISA_MIPS32;
+def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd>, MFC3OP_FM<0x12, 0>;
+def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd>, MFC3OP_FM<0x12, 4>;
- let isCTI = 1 in
- def PAUSE : MMRel, StdMMR6Rel, Barrier<"pause", II_PAUSE>, BARRIER_FM<5>,
- ISA_MIPS32R2;
-}
+class Barrier<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary,
+ FrmOther, asmstr>;
+def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop">, BARRIER_FM<1>;
+def EHB : MMRel, Barrier<"ehb">, BARRIER_FM<3>;
+def PAUSE : MMRel, StdMMR6Rel, Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2;
// JR_HB and JALR_HB are defined here using the new style naming
// scheme because some of this code is shared with Mips32r6InstrInfo.td
@@ -2471,64 +1724,46 @@ class JALR_HB_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
list<dag> Pattern = [];
}
-class JR_HB_DESC<RegisterOperand RO> :
- InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>, JR_HB_DESC_BASE<"jr.hb", RO> {
+class JR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>,
+ JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> {
let isBranch=1;
let isIndirectBranch=1;
let hasDelaySlot=1;
let isTerminator=1;
let isBarrier=1;
- bit isCTI = 1;
}
-class JALR_HB_DESC<RegisterOperand RO> :
- InstSE<(outs), (ins), "", [], II_JALR_HB, FrmJ>, JALR_HB_DESC_BASE<"jalr.hb",
- RO> {
+class JALR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>,
+ JALR_HB_DESC_BASE<"jalr.hb", GPR32Opnd> {
let isIndirectBranch=1;
let hasDelaySlot=1;
- bit isCTI = 1;
}
class JR_HB_ENC : JR_HB_FM<8>;
class JALR_HB_ENC : JALR_HB_FM<9>;
-def JR_HB : JR_HB_DESC<GPR32Opnd>, JR_HB_ENC, ISA_MIPS32R2_NOT_32R6_64R6;
-def JALR_HB : JALR_HB_DESC<GPR32Opnd>, JALR_HB_ENC, ISA_MIPS32;
+def JR_HB : JR_HB_DESC, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6;
+def JALR_HB : JALR_HB_DESC, JALR_HB_ENC, ISA_MIPS32;
-let AdditionalPredicates = [NotInMicroMips, UseIndirectJumpsHazard] in
- def JALRHBPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR_HB, RA>;
+class TLB<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary,
+ FrmOther, asmstr>;
+def TLBP : MMRel, TLB<"tlbp">, COP0_TLB_FM<0x08>;
+def TLBR : MMRel, TLB<"tlbr">, COP0_TLB_FM<0x01>;
+def TLBWI : MMRel, TLB<"tlbwi">, COP0_TLB_FM<0x02>;
+def TLBWR : MMRel, TLB<"tlbwr">, COP0_TLB_FM<0x06>;
-
-let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips,
- UseIndirectJumpsHazard] in {
- def TAILCALLREGHB : TailCallReg<JR_HB, GPR32Opnd>, ISA_MIPS32_NOT_32R6_64R6;
- def PseudoIndirectHazardBranch : PseudoIndirectBranchBase<JR_HB, GPR32Opnd>,
- ISA_MIPS32R2_NOT_32R6_64R6;
-}
-
-class TLB<string asmstr, InstrItinClass itin = NoItinerary> :
- InstSE<(outs), (ins), asmstr, [], itin, FrmOther, asmstr>;
-let AdditionalPredicates = [NotInMicroMips] in {
- def TLBP : MMRel, TLB<"tlbp", II_TLBP>, COP0_TLB_FM<0x08>, ISA_MIPS1;
- def TLBR : MMRel, TLB<"tlbr", II_TLBR>, COP0_TLB_FM<0x01>, ISA_MIPS1;
- def TLBWI : MMRel, TLB<"tlbwi", II_TLBWI>, COP0_TLB_FM<0x02>, ISA_MIPS1;
- def TLBWR : MMRel, TLB<"tlbwr", II_TLBWR>, COP0_TLB_FM<0x06>, ISA_MIPS1;
-}
-class CacheOp<string instr_asm, Operand MemOpnd,
- InstrItinClass itin = NoItinerary> :
+class CacheOp<string instr_asm, Operand MemOpnd> :
InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint),
- !strconcat(instr_asm, "\t$hint, $addr"), [], itin, FrmOther,
+ !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther,
instr_asm> {
let DecoderMethod = "DecodeCacheOp";
}
-let AdditionalPredicates = [NotInMicroMips] in {
- def CACHE : MMRel, CacheOp<"cache", mem, II_CACHE>, CACHEOP_FM<0b101111>,
- INSN_MIPS3_32_NOT_32R6_64R6;
- def PREF : MMRel, CacheOp<"pref", mem, II_PREF>, CACHEOP_FM<0b110011>,
- INSN_MIPS3_32_NOT_32R6_64R6;
-}
-// FIXME: We are missing the prefx instruction.
+def CACHE : MMRel, CacheOp<"cache", mem>, CACHEOP_FM<0b101111>,
+ INSN_MIPS3_32_NOT_32R6_64R6;
+def PREF : MMRel, CacheOp<"pref", mem>, CACHEOP_FM<0b110011>,
+ INSN_MIPS3_32_NOT_32R6_64R6;
+
def ROL : MipsAsmPseudoInst<(outs),
(ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd),
"rol\t$rs, $rt, $rd">;
@@ -2573,193 +1808,87 @@ def : MipsInstAlias<"dror $rd, $rs",
def : MipsInstAlias<"dror $rd, $imm",
(DRORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, ISA_MIPS64;
-def ABSMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs),
- "abs\t$rd, $rs">;
-
-def SEQMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "seq $rd, $rs, $rt">, NOT_ASE_CNMIPS;
-
-def : MipsInstAlias<"seq $rd, $rs",
- (SEQMacro GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>,
- NOT_ASE_CNMIPS;
-
-def SEQIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, simm32_relaxed:$imm),
- "seq $rd, $rs, $imm">, NOT_ASE_CNMIPS;
-
-def : MipsInstAlias<"seq $rd, $imm",
- (SEQIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, simm32:$imm), 0>,
- NOT_ASE_CNMIPS;
-
-def MULImmMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs,
- simm32_relaxed:$imm),
- "mul\t$rd, $rs, $imm">,
- ISA_MIPS1_NOT_32R6_64R6;
-def MULOMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs,
- GPR32Opnd:$rt),
- "mulo\t$rd, $rs, $rt">,
- ISA_MIPS1_NOT_32R6_64R6;
-def MULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs,
- GPR32Opnd:$rt),
- "mulou\t$rd, $rs, $rt">,
- ISA_MIPS1_NOT_32R6_64R6;
-
-// Virtualization ASE
-class HYPCALL_FT<string opstr> :
- InstSE<(outs), (ins uimm10:$code_),
- !strconcat(opstr, "\t$code_"), [], II_HYPCALL, FrmOther, opstr> {
- let BaseOpcode = opstr;
-}
-
-let AdditionalPredicates = [NotInMicroMips] in {
- def MFGC0 : MMRel, MFC3OP<"mfgc0", GPR32Opnd, COP0Opnd, II_MFGC0>,
- MFC3OP_FM<0x10, 3, 0>, ISA_MIPS32R5, ASE_VIRT;
- def MTGC0 : MMRel, MTC3OP<"mtgc0", COP0Opnd, GPR32Opnd, II_MTGC0>,
- MFC3OP_FM<0x10, 3, 2>, ISA_MIPS32R5, ASE_VIRT;
- def MFHGC0 : MMRel, MFC3OP<"mfhgc0", GPR32Opnd, COP0Opnd, II_MFHGC0>,
- MFC3OP_FM<0x10, 3, 4>, ISA_MIPS32R5, ASE_VIRT;
- def MTHGC0 : MMRel, MTC3OP<"mthgc0", COP0Opnd, GPR32Opnd, II_MTHGC0>,
- MFC3OP_FM<0x10, 3, 6>, ISA_MIPS32R5, ASE_VIRT;
- def TLBGINV : MMRel, TLB<"tlbginv", II_TLBGINV>, COP0_TLB_FM<0b001011>,
- ISA_MIPS32R5, ASE_VIRT;
- def TLBGINVF : MMRel, TLB<"tlbginvf", II_TLBGINVF>, COP0_TLB_FM<0b001100>,
- ISA_MIPS32R5, ASE_VIRT;
- def TLBGP : MMRel, TLB<"tlbgp", II_TLBGP>, COP0_TLB_FM<0b010000>,
- ISA_MIPS32R5, ASE_VIRT;
- def TLBGR : MMRel, TLB<"tlbgr", II_TLBGR>, COP0_TLB_FM<0b001001>,
- ISA_MIPS32R5, ASE_VIRT;
- def TLBGWI : MMRel, TLB<"tlbgwi", II_TLBGWI>, COP0_TLB_FM<0b001010>,
- ISA_MIPS32R5, ASE_VIRT;
- def TLBGWR : MMRel, TLB<"tlbgwr", II_TLBGWR>, COP0_TLB_FM<0b001110>,
- ISA_MIPS32R5, ASE_VIRT;
- def HYPCALL : MMRel, HYPCALL_FT<"hypcall">,
- HYPCALL_FM<0b101000>, ISA_MIPS32R5, ASE_VIRT;
-}
-
//===----------------------------------------------------------------------===//
// Instruction aliases
//===----------------------------------------------------------------------===//
-
-multiclass OneOrTwoOperandMacroImmediateAlias<string Memnomic,
- Instruction Opcode,
- RegisterOperand RO = GPR32Opnd,
- Operand Imm = simm32_relaxed> {
- def : MipsInstAlias<!strconcat(Memnomic, " $rs, $rt, $imm"),
- (Opcode RO:$rs,
- RO:$rt,
- Imm:$imm), 0>;
- def : MipsInstAlias<!strconcat(Memnomic, " $rs, $imm"),
- (Opcode RO:$rs,
- RO:$rs,
- Imm:$imm), 0>;
+def : MipsInstAlias<"move $dst, $src",
+ (OR GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>,
+ GPR_32 {
+ let AdditionalPredicates = [NotInMicroMips];
}
-
+def : MipsInstAlias<"move $dst, $src",
+ (ADDu GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>,
+ GPR_32 {
+ let AdditionalPredicates = [NotInMicroMips];
+}
+def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<"addu $rs, $rt, $imm",
+ (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
+def : MipsInstAlias<"addu $rs, $imm",
+ (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>;
+def : MipsInstAlias<"add $rs, $rt, $imm",
+ (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<"add $rs, $imm",
+ (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<"and $rs, $rt, $imm",
+ (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
+def : MipsInstAlias<"and $rs, $imm",
+ (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>;
+def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>;
+let Predicates = [NotInMicroMips] in {
+def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>;
+}
+def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, ISA_MIPS32;
+def : MipsInstAlias<"not $rt, $rs",
+ (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>;
+def : MipsInstAlias<"neg $rt, $rs",
+ (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>;
+def : MipsInstAlias<"negu $rt",
+ (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 0>;
+def : MipsInstAlias<"negu $rt, $rs",
+ (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>;
+def : MipsInstAlias<"slt $rs, $rt, $imm",
+ (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
+def : MipsInstAlias<"sltu $rt, $rs, $imm",
+ (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm16:$imm), 0>;
+def : MipsInstAlias<"xor $rs, $rt, $imm",
+ (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
+def : MipsInstAlias<"xor $rs, $imm",
+ (XORi GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>;
+def : MipsInstAlias<"or $rs, $rt, $imm",
+ (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
+def : MipsInstAlias<"or $rs, $imm",
+ (ORi GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>;
+let AdditionalPredicates = [NotInMicroMips] in {
+def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>;
+}
+def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>;
+def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, COP2Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 COP2Opnd:$rd, GPR32Opnd:$rt, 0), 0>;
+let AdditionalPredicates = [NotInMicroMips] in {
+def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>;
+}
+def : MipsInstAlias<"bnez $rs,$offset",
+ (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
+def : MipsInstAlias<"bnezl $rs,$offset",
+ (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
+def : MipsInstAlias<"beqz $rs,$offset",
+ (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
+def : MipsInstAlias<"beqzl $rs,$offset",
+ (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
+def : MipsInstAlias<"syscall", (SYSCALL 0), 1>;
+
+def : MipsInstAlias<"break", (BREAK 0, 0), 1>;
+def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>;
let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsInstAlias<"move $dst, $src",
- (OR GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>,
- GPR_32, ISA_MIPS1;
- def : MipsInstAlias<"move $dst, $src",
- (ADDu GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>,
- GPR_32, ISA_MIPS1;
-
- def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 1>,
- ISA_MIPS1_NOT_32R6_64R6;
-
- def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>, ISA_MIPS1;
-
- def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>;
-
- def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>,
- ISA_MIPS32;
-
- def : MipsInstAlias<"neg $rt, $rs",
- (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS1;
- def : MipsInstAlias<"neg $rt",
- (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, ISA_MIPS1;
- def : MipsInstAlias<"negu $rt, $rs",
- (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS1;
- def : MipsInstAlias<"negu $rt",
- (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, ISA_MIPS1;
- def : MipsInstAlias<
- "sgt $rd, $rs, $rt",
- (SLT GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1;
- def : MipsInstAlias<
- "sgt $rs, $rt",
- (SLT GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1;
- def : MipsInstAlias<
- "sgtu $rd, $rs, $rt",
- (SLTu GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1;
- def : MipsInstAlias<
- "sgtu $$rs, $rt",
- (SLTu GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1;
- def : MipsInstAlias<
- "not $rt, $rs",
- (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>, ISA_MIPS1;
- def : MipsInstAlias<
- "not $rt",
- (NOR GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>, ISA_MIPS1;
-
- def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>, ISA_MIPS1;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi>, ISA_MIPS1_NOT_32R6_64R6;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu>, ISA_MIPS1;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi>, ISA_MIPS1, GPR_32;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi>, ISA_MIPS1, GPR_32;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi>, ISA_MIPS1, GPR_32;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi>, ISA_MIPS1, GPR_32;
-
- defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu>, ISA_MIPS1, GPR_32;
-
- def : MipsInstAlias<"mfgc0 $rt, $rd",
- (MFGC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>,
- ISA_MIPS32R5, ASE_VIRT;
- def : MipsInstAlias<"mtgc0 $rt, $rd",
- (MTGC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>,
- ISA_MIPS32R5, ASE_VIRT;
- def : MipsInstAlias<"mfhgc0 $rt, $rd",
- (MFHGC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>,
- ISA_MIPS32R5, ASE_VIRT;
- def : MipsInstAlias<"mthgc0 $rt, $rd",
- (MTHGC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>,
- ISA_MIPS32R5, ASE_VIRT;
- def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>,
- ISA_MIPS1;
- def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>,
- ISA_MIPS1;
- def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, COP2Opnd:$rd, 0), 0>,
- ISA_MIPS1;
- def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 COP2Opnd:$rd, GPR32Opnd:$rt, 0), 0>,
- ISA_MIPS1;
-
- def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>,
- ISA_MIPS1;
-
- def : MipsInstAlias<"bnez $rs,$offset",
- (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>,
- ISA_MIPS1;
- def : MipsInstAlias<"bnezl $rs,$offset",
- (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>,
- ISA_MIPS2;
- def : MipsInstAlias<"beqz $rs,$offset",
- (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>,
- ISA_MIPS1;
- def : MipsInstAlias<"beqzl $rs,$offset",
- (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>,
- ISA_MIPS2;
-
- def : MipsInstAlias<"syscall", (SYSCALL 0), 1>, ISA_MIPS1;
-
- def : MipsInstAlias<"break", (BREAK 0, 0), 1>, ISA_MIPS1;
- def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>, ISA_MIPS1;
def : MipsInstAlias<"ei", (EI ZERO), 1>, ISA_MIPS32R2;
def : MipsInstAlias<"di", (DI ZERO), 1>, ISA_MIPS32R2;
-
+}
+let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"teq $rs, $rt",
(TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2;
def : MipsInstAlias<"tge $rs, $rt",
@@ -2772,10 +1901,9 @@ let AdditionalPredicates = [NotInMicroMips] in {
(TLTU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2;
def : MipsInstAlias<"tne $rs, $rt",
(TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2;
- def : MipsInstAlias<"rdhwr $rt, $rs",
- (RDHWR GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, ISA_MIPS1;
-
}
+def : MipsInstAlias<"sll $rd, $rt, $rs",
+ (SLLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
def : MipsInstAlias<"sub, $rd, $rs, $imm",
(ADDi GPR32Opnd:$rd, GPR32Opnd:$rs,
InvertedImOperand:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6;
@@ -2787,48 +1915,21 @@ def : MipsInstAlias<"subu, $rd, $rs, $imm",
InvertedImOperand:$imm), 0>;
def : MipsInstAlias<"subu $rs, $imm", (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs,
InvertedImOperand:$imm), 0>;
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsInstAlias<"sll $rd, $rt, $rs",
- (SLLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
- def : MipsInstAlias<"sra $rd, $rt, $rs",
- (SRAV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
- def : MipsInstAlias<"srl $rd, $rt, $rs",
- (SRLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
- def : MipsInstAlias<"sll $rd, $rt",
- (SLLV GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>;
- def : MipsInstAlias<"sra $rd, $rt",
- (SRAV GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>;
- def : MipsInstAlias<"srl $rd, $rt",
- (SRLV GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>;
- def : MipsInstAlias<"seh $rd", (SEH GPR32Opnd:$rd, GPR32Opnd:$rd), 0>,
- ISA_MIPS32R2;
- def : MipsInstAlias<"seb $rd", (SEB GPR32Opnd:$rd, GPR32Opnd:$rd), 0>,
- ISA_MIPS32R2;
-}
+def : MipsInstAlias<"sra $rd, $rt, $rs",
+ (SRAV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
+def : MipsInstAlias<"srl $rd, $rt, $rs",
+ (SRLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
def : MipsInstAlias<"sdbbp", (SDBBP 0)>, ISA_MIPS32_NOT_32R6_64R6;
-let AdditionalPredicates = [NotInMicroMips] in
- def : MipsInstAlias<"sync", (SYNC 0), 1>, ISA_MIPS2;
-
-def : MipsInstAlias<"mulo $rs, $rt",
- (MULOMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"mulou $rs, $rt",
- (MULOUMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-
-let AdditionalPredicates = [NotInMicroMips] in
- def : MipsInstAlias<"hypcall", (HYPCALL 0), 1>, ISA_MIPS32R5, ASE_VIRT;
-
+def : MipsInstAlias<"sync",
+ (SYNC 0), 1>, ISA_MIPS2;
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions
//===----------------------------------------------------------------------===//
-// We use uimm32_coerced to accept a 33 bit signed number that is rendered into
-// a 32 bit number.
class LoadImmediate32<string instr_asm, Operand Od, RegisterOperand RO> :
MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32),
!strconcat(instr_asm, "\t$rt, $imm32")> ;
-def LoadImm32 : LoadImmediate32<"li", uimm32_coerced, GPR32Opnd>;
+def LoadImm32 : LoadImmediate32<"li", simm32, GPR32Opnd>;
class LoadAddressFromReg32<string instr_asm, Operand MemOpnd,
RegisterOperand RO> :
@@ -2839,21 +1940,17 @@ def LoadAddrReg32 : LoadAddressFromReg32<"la", mem, GPR32Opnd>;
class LoadAddressFromImm32<string instr_asm, Operand Od, RegisterOperand RO> :
MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32),
!strconcat(instr_asm, "\t$rt, $imm32")> ;
-def LoadAddrImm32 : LoadAddressFromImm32<"la", i32imm, GPR32Opnd>;
+def LoadAddrImm32 : LoadAddressFromImm32<"la", simm32, GPR32Opnd>;
def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs),
"jal\t$rd, $rs"> ;
def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs),
"jal\t$rs"> ;
-class NORIMM_DESC_BASE<RegisterOperand RO, DAGOperand Imm> :
- MipsAsmPseudoInst<(outs RO:$rs), (ins RO:$rt, Imm:$imm),
- "nor\t$rs, $rt, $imm">;
-def NORImm : NORIMM_DESC_BASE<GPR32Opnd, simm32_relaxed>, GPR_32;
-def : MipsInstAlias<"nor\t$rs, $imm", (NORImm GPR32Opnd:$rs, GPR32Opnd:$rs,
- simm32_relaxed:$imm)>, GPR_32;
+def NORImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm),
+ "nor\t$rs, $rt, $imm"> ;
-let hasDelaySlot = 1, isCTI = 1 in {
+let hasDelaySlot = 1 in {
def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
(ins imm64:$imm64, brtarget:$offset),
"bne\t$rt, $imm64, $offset">;
@@ -2884,14 +1981,10 @@ def BLEUL: CondBranchPseudo<"bleul">, ISA_MIPS2_NOT_32R6_64R6;
def BGEUL: CondBranchPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6;
def BGTUL: CondBranchPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6;
-let isCTI = 1 in
class CondBranchImmPseudo<string instr_asm> :
MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset),
!strconcat(instr_asm, "\t$rs, $imm, $offset")>;
-def BEQLImmMacro : CondBranchImmPseudo<"beql">, ISA_MIPS2_NOT_32R6_64R6;
-def BNELImmMacro : CondBranchImmPseudo<"bnel">, ISA_MIPS2_NOT_32R6_64R6;
-
def BLTImmMacro : CondBranchImmPseudo<"blt">;
def BLEImmMacro : CondBranchImmPseudo<"ble">;
def BGEImmMacro : CondBranchImmPseudo<"bge">;
@@ -2915,76 +2008,17 @@ def BGTULImmMacro : CondBranchImmPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6;
// Once the tablegen-erated errors are made better, this needs to be fixed and
// predicates needs to be restored.
-def SDivMacro : MipsAsmPseudoInst<(outs GPR32NonZeroOpnd:$rd),
- (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "div\t$rd, $rs, $rt">,
- ISA_MIPS1_NOT_32R6_64R6;
-def SDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, simm32:$imm),
- "div\t$rd, $rs, $imm">,
- ISA_MIPS1_NOT_32R6_64R6;
-def UDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "divu\t$rd, $rs, $rt">,
- ISA_MIPS1_NOT_32R6_64R6;
-def UDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, simm32:$imm),
- "divu\t$rd, $rs, $imm">,
- ISA_MIPS1_NOT_32R6_64R6;
-
-
-def : MipsInstAlias<"div $rs, $rt", (SDIV GPR32ZeroOpnd:$rs,
- GPR32Opnd:$rt), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"div $rs, $rt", (SDivMacro GPR32NonZeroOpnd:$rs,
- GPR32NonZeroOpnd:$rs,
- GPR32Opnd:$rt), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"div $rd, $imm", (SDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
- simm32:$imm), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
+def SDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
+ "div\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"divu $rt, $rs", (UDIV GPR32ZeroOpnd:$rt,
- GPR32Opnd:$rs), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"divu $rt, $rs", (UDivMacro GPR32NonZeroOpnd:$rt,
- GPR32NonZeroOpnd:$rt,
- GPR32Opnd:$rs), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
+def UDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
+ "divu\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
- simm32:$imm), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
+def DSDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
+ "ddiv\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6;
-def SRemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "rem\t$rd, $rs, $rt">,
- ISA_MIPS1_NOT_32R6_64R6;
-def SRemIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, simm32_relaxed:$imm),
- "rem\t$rd, $rs, $imm">,
- ISA_MIPS1_NOT_32R6_64R6;
-def URemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "remu\t$rd, $rs, $rt">,
- ISA_MIPS1_NOT_32R6_64R6;
-def URemIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
- (ins GPR32Opnd:$rs, simm32_relaxed:$imm),
- "remu\t$rd, $rs, $imm">,
- ISA_MIPS1_NOT_32R6_64R6;
-
-def : MipsInstAlias<"rem $rt, $rs", (SRemMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
- GPR32Opnd:$rs), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"rem $rd, $imm", (SRemIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
- simm32_relaxed:$imm), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"remu $rt, $rs", (URemMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
- GPR32Opnd:$rs), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"remu $rd, $imm", (URemIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
- simm32_relaxed:$imm), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
+def DUDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
+ "ddivu\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6;
def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
"ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
@@ -2995,18 +2029,6 @@ def Ulhu : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
def Ulw : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
"ulw\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
-def Ush : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
- "ush\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
-
-def Usw : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
- "usw\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
-
-def LDMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
- (ins mem_simm16:$addr), "ld $rt, $addr">,
- ISA_MIPS1_NOT_MIPS3;
-def SDMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
- (ins mem_simm16:$addr), "sd $rt, $addr">,
- ISA_MIPS1_NOT_MIPS3;
//===----------------------------------------------------------------------===//
// Arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
@@ -3018,39 +2040,29 @@ class LoadRegImmPat<Instruction LoadInst, ValueType ValTy, PatFrag Node> :
class StoreRegImmPat<Instruction StoreInst, ValueType ValTy> :
MipsPat<(store ValTy:$v, addrRegImm:$a), (StoreInst ValTy:$v, addrRegImm:$a)>;
-// Materialize constants.
-multiclass MaterializeImms<ValueType VT, Register ZEROReg,
- Instruction ADDiuOp, Instruction LUiOp,
- Instruction ORiOp> {
-
-// Constant synthesis previously relied on the ordering of the patterns below.
-// By making the predicates they use non-overlapping, the patterns were
-// reordered so that the effect of the newly introduced predicates can be
-// observed.
-
-// Arbitrary immediates
-def : MipsPat<(VT LUiORiPred:$imm), (ORiOp (LUiOp (HI16 imm:$imm)), (LO16 imm:$imm))>;
-
-// Bits 32-16 set, sign/zero extended.
-def : MipsPat<(VT LUiPred:$imm), (LUiOp (HI16 imm:$imm))>;
-
// Small immediates
-def : MipsPat<(VT ORiPred:$imm), (ORiOp ZEROReg, imm:$imm)>;
-def : MipsPat<(VT immSExt16:$imm), (ADDiuOp ZEROReg, imm:$imm)>;
+let AdditionalPredicates = [NotInMicroMips] in {
+def : MipsPat<(i32 immSExt16:$in),
+ (ADDiu ZERO, imm:$in)>;
+def : MipsPat<(i32 immZExt16:$in),
+ (ORi ZERO, imm:$in)>;
}
+def : MipsPat<(i32 immLow16Zero:$in),
+ (LUi (HI16 imm:$in))>;
-let AdditionalPredicates = [NotInMicroMips] in
- defm : MaterializeImms<i32, ZERO, ADDiu, LUi, ORi>, ISA_MIPS1;
+// Arbitrary immediates
+def : MipsPat<(i32 imm:$imm),
+ (ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>;
// Carry MipsPatterns
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs),
- (SUBu GPR32:$lhs, GPR32:$rhs)>, ISA_MIPS1;
+def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs),
+ (SUBu GPR32:$lhs, GPR32:$rhs)>;
+let AdditionalPredicates = [NotDSP] in {
+ def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs),
+ (ADDu GPR32:$lhs, GPR32:$rhs)>;
+ def : MipsPat<(addc GPR32:$src, immSExt16:$imm),
+ (ADDiu GPR32:$src, imm:$imm)>;
}
-def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs),
- (ADDu GPR32:$lhs, GPR32:$rhs)>, ISA_MIPS1, ASE_NOT_DSP;
-def : MipsPat<(addc GPR32:$src, immSExt16:$imm),
- (ADDiu GPR32:$src, imm:$imm)>, ISA_MIPS1, ASE_NOT_DSP;
// Support multiplication for pre-Mips32 targets that don't have
// the MUL instruction.
@@ -3064,128 +2076,110 @@ def : MipsPat<(MipsSync (i32 immz)),
// Call
def : MipsPat<(MipsJmpLink (i32 texternalsym:$dst)),
- (JAL texternalsym:$dst)>, ISA_MIPS1;
+ (JAL texternalsym:$dst)>;
//def : MipsPat<(MipsJmpLink GPR32:$dst),
// (JALR GPR32:$dst)>;
// Tail call
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)),
- (TAILCALL tglobaladdr:$dst)>, ISA_MIPS1;
- def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)),
- (TAILCALL texternalsym:$dst)>, ISA_MIPS1;
-}
+def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)),
+ (TAILCALL tglobaladdr:$dst)>;
+def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)),
+ (TAILCALL texternalsym:$dst)>;
// hi/lo relocs
-multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu,
- Register ZeroReg, RegisterOperand GPROpnd> {
- def : MipsPat<(MipsHi tglobaladdr:$in), (Lui tglobaladdr:$in)>;
- def : MipsPat<(MipsHi tblockaddress:$in), (Lui tblockaddress:$in)>;
- def : MipsPat<(MipsHi tjumptable:$in), (Lui tjumptable:$in)>;
- def : MipsPat<(MipsHi tconstpool:$in), (Lui tconstpool:$in)>;
- def : MipsPat<(MipsHi texternalsym:$in), (Lui texternalsym:$in)>;
-
- def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>;
- def : MipsPat<(MipsLo tblockaddress:$in),
- (Addiu ZeroReg, tblockaddress:$in)>;
- def : MipsPat<(MipsLo tjumptable:$in), (Addiu ZeroReg, tjumptable:$in)>;
- def : MipsPat<(MipsLo tconstpool:$in), (Addiu ZeroReg, tconstpool:$in)>;
- def : MipsPat<(MipsLo tglobaltlsaddr:$in),
- (Addiu ZeroReg, tglobaltlsaddr:$in)>;
- def : MipsPat<(MipsLo texternalsym:$in), (Addiu ZeroReg, texternalsym:$in)>;
-
- def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaladdr:$lo)),
- (Addiu GPROpnd:$hi, tglobaladdr:$lo)>;
- def : MipsPat<(add GPROpnd:$hi, (MipsLo tblockaddress:$lo)),
- (Addiu GPROpnd:$hi, tblockaddress:$lo)>;
- def : MipsPat<(add GPROpnd:$hi, (MipsLo tjumptable:$lo)),
- (Addiu GPROpnd:$hi, tjumptable:$lo)>;
- def : MipsPat<(add GPROpnd:$hi, (MipsLo tconstpool:$lo)),
- (Addiu GPROpnd:$hi, tconstpool:$lo)>;
- def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaltlsaddr:$lo)),
- (Addiu GPROpnd:$hi, tglobaltlsaddr:$lo)>;
-}
+def : MipsPat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
+def : MipsPat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>;
+def : MipsPat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>;
+def : MipsPat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>;
+def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>;
+def : MipsPat<(MipsHi texternalsym:$in), (LUi texternalsym:$in)>;
+
+def : MipsPat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
+def : MipsPat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>;
+def : MipsPat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>;
+def : MipsPat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>;
+def : MipsPat<(MipsLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>;
+def : MipsPat<(MipsLo texternalsym:$in), (ADDiu ZERO, texternalsym:$in)>;
+
+def : MipsPat<(add GPR32:$hi, (MipsLo tglobaladdr:$lo)),
+ (ADDiu GPR32:$hi, tglobaladdr:$lo)>;
+def : MipsPat<(add GPR32:$hi, (MipsLo tblockaddress:$lo)),
+ (ADDiu GPR32:$hi, tblockaddress:$lo)>;
+def : MipsPat<(add GPR32:$hi, (MipsLo tjumptable:$lo)),
+ (ADDiu GPR32:$hi, tjumptable:$lo)>;
+def : MipsPat<(add GPR32:$hi, (MipsLo tconstpool:$lo)),
+ (ADDiu GPR32:$hi, tconstpool:$lo)>;
+def : MipsPat<(add GPR32:$hi, (MipsLo tglobaltlsaddr:$lo)),
+ (ADDiu GPR32:$hi, tglobaltlsaddr:$lo)>;
+
+// gp_rel relocs
+def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)),
+ (ADDiu GPR32:$gp, tglobaladdr:$in)>;
+def : MipsPat<(add GPR32:$gp, (MipsGPRel tconstpool:$in)),
+ (ADDiu GPR32:$gp, tconstpool:$in)>;
// wrapper_pic
class WrapperPat<SDNode node, Instruction ADDiuOp, RegisterClass RC>:
- MipsPat<(MipsWrapper RC:$gp, node:$in), (ADDiuOp RC:$gp, node:$in)>;
-
-let AdditionalPredicates = [NotInMicroMips] in {
- defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>, ISA_MIPS1;
-
- def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi tglobaladdr:$in)>, ISA_MIPS1;
- def : MipsPat<(MipsGotHi texternalsym:$in), (LUi texternalsym:$in)>,
- ISA_MIPS1;
+ MipsPat<(MipsWrapper RC:$gp, node:$in),
+ (ADDiuOp RC:$gp, node:$in)>;
- def : MipsPat<(MipsTlsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>,
- ISA_MIPS1;
+def : WrapperPat<tglobaladdr, ADDiu, GPR32>;
+def : WrapperPat<tconstpool, ADDiu, GPR32>;
+def : WrapperPat<texternalsym, ADDiu, GPR32>;
+def : WrapperPat<tblockaddress, ADDiu, GPR32>;
+def : WrapperPat<tjumptable, ADDiu, GPR32>;
+def : WrapperPat<tglobaltlsaddr, ADDiu, GPR32>;
- // gp_rel relocs
- def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)),
- (ADDiu GPR32:$gp, tglobaladdr:$in)>, ISA_MIPS1, ABI_NOT_N64;
- def : MipsPat<(add GPR32:$gp, (MipsGPRel tconstpool:$in)),
- (ADDiu GPR32:$gp, tconstpool:$in)>, ISA_MIPS1, ABI_NOT_N64;
-
- def : WrapperPat<tglobaladdr, ADDiu, GPR32>, ISA_MIPS1;
- def : WrapperPat<tconstpool, ADDiu, GPR32>, ISA_MIPS1;
- def : WrapperPat<texternalsym, ADDiu, GPR32>, ISA_MIPS1;
- def : WrapperPat<tblockaddress, ADDiu, GPR32>, ISA_MIPS1;
- def : WrapperPat<tjumptable, ADDiu, GPR32>, ISA_MIPS1;
- def : WrapperPat<tglobaltlsaddr, ADDiu, GPR32>, ISA_MIPS1;
-
- // Mips does not have "not", so we expand our way
- def : MipsPat<(not GPR32:$in),
- (NOR GPR32Opnd:$in, ZERO)>, ISA_MIPS1;
+let AdditionalPredicates = [NotInMicroMips] in {
+// Mips does not have "not", so we expand our way
+def : MipsPat<(not GPR32:$in),
+ (NOR GPR32Opnd:$in, ZERO)>;
}
// extended loads
-let AdditionalPredicates = [NotInMicroMips] in {
- def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>, ISA_MIPS1;
- def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>, ISA_MIPS1;
- def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>, ISA_MIPS1;
+def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>;
+def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>;
+def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
- // peepholes
- def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>, ISA_MIPS1;
-}
+// peepholes
+def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
// brcond patterns
-multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BEQOp1,
- Instruction BNEOp, Instruction SLTOp, Instruction SLTuOp,
- Instruction SLTiOp, Instruction SLTiuOp,
- Register ZEROReg> {
+multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BNEOp,
+ Instruction SLTOp, Instruction SLTuOp, Instruction SLTiOp,
+ Instruction SLTiuOp, Register ZEROReg> {
def : MipsPat<(brcond (i32 (setne RC:$lhs, 0)), bb:$dst),
(BNEOp RC:$lhs, ZEROReg, bb:$dst)>;
def : MipsPat<(brcond (i32 (seteq RC:$lhs, 0)), bb:$dst),
(BEQOp RC:$lhs, ZEROReg, bb:$dst)>;
def : MipsPat<(brcond (i32 (setge RC:$lhs, RC:$rhs)), bb:$dst),
- (BEQOp1 (SLTOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>;
+ (BEQ (SLTOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>;
def : MipsPat<(brcond (i32 (setuge RC:$lhs, RC:$rhs)), bb:$dst),
- (BEQOp1 (SLTuOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>;
+ (BEQ (SLTuOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>;
def : MipsPat<(brcond (i32 (setge RC:$lhs, immSExt16:$rhs)), bb:$dst),
- (BEQOp1 (SLTiOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
+ (BEQ (SLTiOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
def : MipsPat<(brcond (i32 (setuge RC:$lhs, immSExt16:$rhs)), bb:$dst),
- (BEQOp1 (SLTiuOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
+ (BEQ (SLTiuOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
def : MipsPat<(brcond (i32 (setgt RC:$lhs, immSExt16Plus1:$rhs)), bb:$dst),
- (BEQOp1 (SLTiOp RC:$lhs, (Plus1 imm:$rhs)), ZERO, bb:$dst)>;
+ (BEQ (SLTiOp RC:$lhs, (Plus1 imm:$rhs)), ZERO, bb:$dst)>;
def : MipsPat<(brcond (i32 (setugt RC:$lhs, immSExt16Plus1:$rhs)), bb:$dst),
- (BEQOp1 (SLTiuOp RC:$lhs, (Plus1 imm:$rhs)), ZERO, bb:$dst)>;
+ (BEQ (SLTiuOp RC:$lhs, (Plus1 imm:$rhs)), ZERO, bb:$dst)>;
def : MipsPat<(brcond (i32 (setle RC:$lhs, RC:$rhs)), bb:$dst),
- (BEQOp1 (SLTOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>;
+ (BEQ (SLTOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>;
def : MipsPat<(brcond (i32 (setule RC:$lhs, RC:$rhs)), bb:$dst),
- (BEQOp1 (SLTuOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>;
+ (BEQ (SLTuOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>;
def : MipsPat<(brcond RC:$cond, bb:$dst),
(BNEOp RC:$cond, ZEROReg, bb:$dst)>;
}
-let AdditionalPredicates = [NotInMicroMips] in {
- defm : BrcondPats<GPR32, BEQ, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>,
- ISA_MIPS1;
- def : MipsPat<(brcond (i32 (setlt i32:$lhs, 1)), bb:$dst),
- (BLEZ i32:$lhs, bb:$dst)>, ISA_MIPS1;
- def : MipsPat<(brcond (i32 (setgt i32:$lhs, -1)), bb:$dst),
- (BGEZ i32:$lhs, bb:$dst)>, ISA_MIPS1;
-}
+
+defm : BrcondPats<GPR32, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>;
+
+def : MipsPat<(brcond (i32 (setlt i32:$lhs, 1)), bb:$dst),
+ (BLEZ i32:$lhs, bb:$dst)>;
+def : MipsPat<(brcond (i32 (setgt i32:$lhs, -1)), bb:$dst),
+ (BGEZ i32:$lhs, bb:$dst)>;
// setcc patterns
multiclass SeteqPats<RegisterClass RC, Instruction SLTiuOp, Instruction XOROp,
@@ -3200,12 +2194,11 @@ multiclass SeteqPats<RegisterClass RC, Instruction SLTiuOp, Instruction XOROp,
(SLTuOp ZEROReg, (XOROp RC:$lhs, RC:$rhs))>;
}
-multiclass SetlePats<RegisterClass RC, Instruction XORiOp, Instruction SLTOp,
- Instruction SLTuOp> {
+multiclass SetlePats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> {
def : MipsPat<(setle RC:$lhs, RC:$rhs),
- (XORiOp (SLTOp RC:$rhs, RC:$lhs), 1)>;
+ (XORi (SLTOp RC:$rhs, RC:$lhs), 1)>;
def : MipsPat<(setule RC:$lhs, RC:$rhs),
- (XORiOp (SLTuOp RC:$rhs, RC:$lhs), 1)>;
+ (XORi (SLTuOp RC:$rhs, RC:$lhs), 1)>;
}
multiclass SetgtPats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> {
@@ -3215,56 +2208,48 @@ multiclass SetgtPats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> {
(SLTuOp RC:$rhs, RC:$lhs)>;
}
-multiclass SetgePats<RegisterClass RC, Instruction XORiOp, Instruction SLTOp,
- Instruction SLTuOp> {
+multiclass SetgePats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> {
def : MipsPat<(setge RC:$lhs, RC:$rhs),
- (XORiOp (SLTOp RC:$lhs, RC:$rhs), 1)>;
+ (XORi (SLTOp RC:$lhs, RC:$rhs), 1)>;
def : MipsPat<(setuge RC:$lhs, RC:$rhs),
- (XORiOp (SLTuOp RC:$lhs, RC:$rhs), 1)>;
+ (XORi (SLTuOp RC:$lhs, RC:$rhs), 1)>;
}
-multiclass SetgeImmPats<RegisterClass RC, Instruction XORiOp,
- Instruction SLTiOp, Instruction SLTiuOp> {
+multiclass SetgeImmPats<RegisterClass RC, Instruction SLTiOp,
+ Instruction SLTiuOp> {
def : MipsPat<(setge RC:$lhs, immSExt16:$rhs),
- (XORiOp (SLTiOp RC:$lhs, immSExt16:$rhs), 1)>;
+ (XORi (SLTiOp RC:$lhs, immSExt16:$rhs), 1)>;
def : MipsPat<(setuge RC:$lhs, immSExt16:$rhs),
- (XORiOp (SLTiuOp RC:$lhs, immSExt16:$rhs), 1)>;
+ (XORi (SLTiuOp RC:$lhs, immSExt16:$rhs), 1)>;
}
-let AdditionalPredicates = [NotInMicroMips] in {
- defm : SeteqPats<GPR32, SLTiu, XOR, SLTu, ZERO>, ISA_MIPS1;
- defm : SetlePats<GPR32, XORi, SLT, SLTu>, ISA_MIPS1;
- defm : SetgtPats<GPR32, SLT, SLTu>, ISA_MIPS1;
- defm : SetgePats<GPR32, XORi, SLT, SLTu>, ISA_MIPS1;
- defm : SetgeImmPats<GPR32, XORi, SLTi, SLTiu>, ISA_MIPS1;
+defm : SeteqPats<GPR32, SLTiu, XOR, SLTu, ZERO>;
+defm : SetlePats<GPR32, SLT, SLTu>;
+defm : SetgtPats<GPR32, SLT, SLTu>;
+defm : SetgePats<GPR32, SLT, SLTu>;
+defm : SetgeImmPats<GPR32, SLTi, SLTiu>;
- // bswap pattern
- def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>, ISA_MIPS32R2;
-}
+// bswap pattern
+def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>;
// Load halfword/word patterns.
-let AdditionalPredicates = [NotInMicroMips] in {
- let AddedComplexity = 40 in {
- def : LoadRegImmPat<LBu, i32, zextloadi8>, ISA_MIPS1;
- def : LoadRegImmPat<LHu, i32, zextloadi16>, ISA_MIPS1;
- def : LoadRegImmPat<LB, i32, sextloadi8>, ISA_MIPS1;
- def : LoadRegImmPat<LH, i32, sextloadi16>, ISA_MIPS1;
- def : LoadRegImmPat<LW, i32, load>, ISA_MIPS1;
+let AddedComplexity = 40 in {
+ def : LoadRegImmPat<LBu, i32, zextloadi8>;
+ def : LoadRegImmPat<LH, i32, sextloadi16>;
+ let AdditionalPredicates = [NotInMicroMips] in {
+ def : LoadRegImmPat<LW, i32, load>;
}
+}
- // Atomic load patterns.
- def : MipsPat<(atomic_load_8 addr:$a), (LB addr:$a)>, ISA_MIPS1;
- def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>, ISA_MIPS1;
- def : MipsPat<(atomic_load_32 addr:$a), (LW addr:$a)>, ISA_MIPS1;
+// Atomic load patterns.
+def : MipsPat<(atomic_load_8 addr:$a), (LB addr:$a)>;
+def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>;
+def : MipsPat<(atomic_load_32 addr:$a), (LW addr:$a)>;
- // Atomic store patterns.
- def : MipsPat<(atomic_store_8 addr:$a, GPR32:$v), (SB GPR32:$v, addr:$a)>,
- ISA_MIPS1;
- def : MipsPat<(atomic_store_16 addr:$a, GPR32:$v), (SH GPR32:$v, addr:$a)>,
- ISA_MIPS1;
- def : MipsPat<(atomic_store_32 addr:$a, GPR32:$v), (SW GPR32:$v, addr:$a)>,
- ISA_MIPS1;
-}
+// Atomic store patterns.
+def : MipsPat<(atomic_store_8 addr:$a, GPR32:$v), (SB GPR32:$v, addr:$a)>;
+def : MipsPat<(atomic_store_16 addr:$a, GPR32:$v), (SH GPR32:$v, addr:$a)>;
+def : MipsPat<(atomic_store_32 addr:$a, GPR32:$v), (SW GPR32:$v, addr:$a)>;
//===----------------------------------------------------------------------===//
// Floating Point Support
@@ -3295,10 +2280,6 @@ include "MipsMSAInstrInfo.td"
include "MipsEVAInstrFormats.td"
include "MipsEVAInstrInfo.td"
-// MT
-include "MipsMTInstrFormats.td"
-include "MipsMTInstrInfo.td"
-
// Micromips
include "MicroMipsInstrFormats.td"
include "MicroMipsInstrInfo.td"
@@ -3308,6 +2289,10 @@ include "MicroMipsInstrFPU.td"
include "MicroMips32r6InstrFormats.td"
include "MicroMips32r6InstrInfo.td"
+// Micromips64 r6
+include "MicroMips64r6InstrFormats.td"
+include "MicroMips64r6InstrInfo.td"
+
// Micromips DSP
include "MicroMipsDSPInstrFormats.td"
include "MicroMipsDSPInstrInfo.td"
diff --git a/gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h b/gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h
index a282366f6d4..b3222f5d89e 100644
--- a/gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h
+++ b/gnu/llvm/lib/Target/Mips/MipsTargetStreamer.h
@@ -13,7 +13,6 @@
#include "MCTargetDesc/MipsABIFlagsSection.h"
#include "MCTargetDesc/MipsABIInfo.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
@@ -25,12 +24,8 @@ struct MipsABIFlagsSection;
class MipsTargetStreamer : public MCTargetStreamer {
public:
MipsTargetStreamer(MCStreamer &S);
-
- virtual void setPic(bool Value) {}
-
virtual void emitDirectiveSetMicroMips();
virtual void emitDirectiveSetNoMicroMips();
- virtual void setUsesMicroMips();
virtual void emitDirectiveSetMips16();
virtual void emitDirectiveSetNoMips16();
@@ -40,14 +35,6 @@ public:
virtual void emitDirectiveSetNoMacro();
virtual void emitDirectiveSetMsa();
virtual void emitDirectiveSetNoMsa();
- virtual void emitDirectiveSetMt();
- virtual void emitDirectiveSetNoMt();
- virtual void emitDirectiveSetCRC();
- virtual void emitDirectiveSetNoCRC();
- virtual void emitDirectiveSetVirt();
- virtual void emitDirectiveSetNoVirt();
- virtual void emitDirectiveSetGINV();
- virtual void emitDirectiveSetNoGINV();
virtual void emitDirectiveSetAt();
virtual void emitDirectiveSetAtWithArg(unsigned RegNo);
virtual void emitDirectiveSetNoAt();
@@ -83,7 +70,6 @@ public:
virtual void emitDirectiveSetMips64R5();
virtual void emitDirectiveSetMips64R6();
virtual void emitDirectiveSetDsp();
- virtual void emitDirectiveSetDspr2();
virtual void emitDirectiveSetNoDsp();
virtual void emitDirectiveSetPop();
virtual void emitDirectiveSetPush();
@@ -92,9 +78,8 @@ public:
// PIC support
virtual void emitDirectiveCpLoad(unsigned RegNo);
- virtual bool emitDirectiveCpRestore(int Offset,
- function_ref<unsigned()> GetATReg,
- SMLoc IDLoc, const MCSubtargetInfo *STI);
+ virtual void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts,
+ int Offset);
virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg);
virtual void emitDirectiveCpreturn(unsigned SaveLocation,
@@ -105,67 +90,9 @@ public:
virtual void emitDirectiveModuleOddSPReg();
virtual void emitDirectiveModuleSoftFloat();
virtual void emitDirectiveModuleHardFloat();
- virtual void emitDirectiveModuleMT();
virtual void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value);
virtual void emitDirectiveSetOddSPReg();
virtual void emitDirectiveSetNoOddSPReg();
- virtual void emitDirectiveModuleCRC();
- virtual void emitDirectiveModuleNoCRC();
- virtual void emitDirectiveModuleVirt();
- virtual void emitDirectiveModuleNoVirt();
- virtual void emitDirectiveModuleGINV();
- virtual void emitDirectiveModuleNoGINV();
-
- void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
- SMLoc IDLoc, const MCSubtargetInfo *STI);
- void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
- SMLoc IDLoc, const MCSubtargetInfo *STI);
- void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
- SMLoc IDLoc, const MCSubtargetInfo *STI);
- void emitRRIII(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm0,
- int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, bool Is64Bit,
- const MCSubtargetInfo *STI);
- void emitDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
- SMLoc IDLoc, const MCSubtargetInfo *STI);
- void emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI);
-
- /// Emit a store instruction with an offset. If the offset is out of range
- /// then it will be synthesized using the assembler temporary.
- ///
- /// GetATReg() is a callback that can be used to obtain the current assembler
- /// temporary and is only called when the assembler temporary is required. It
- /// must handle the case where no assembler temporary is available (typically
- /// by reporting an error).
- void emitStoreWithImmOffset(unsigned Opcode, unsigned SrcReg,
- unsigned BaseReg, int64_t Offset,
- function_ref<unsigned()> GetATReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitStoreWithSymOffset(unsigned Opcode, unsigned SrcReg,
- unsigned BaseReg, MCOperand &HiOperand,
- MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg,
- int64_t Offset, unsigned TmpReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg,
- MCOperand &HiOperand, MCOperand &LoOperand,
- unsigned ATReg, SMLoc IDLoc,
- const MCSubtargetInfo *STI);
- void emitGPRestore(int Offset, SMLoc IDLoc, const MCSubtargetInfo *STI);
void forbidModuleDirective() { ModuleDirectiveAllowed = false; }
void reallowModuleDirective() { ModuleDirectiveAllowed = true; }
@@ -223,14 +150,6 @@ public:
void emitDirectiveSetNoMacro() override;
void emitDirectiveSetMsa() override;
void emitDirectiveSetNoMsa() override;
- void emitDirectiveSetMt() override;
- void emitDirectiveSetNoMt() override;
- void emitDirectiveSetCRC() override;
- void emitDirectiveSetNoCRC() override;
- void emitDirectiveSetVirt() override;
- void emitDirectiveSetNoVirt() override;
- void emitDirectiveSetGINV() override;
- void emitDirectiveSetNoGINV() override;
void emitDirectiveSetAt() override;
void emitDirectiveSetAtWithArg(unsigned RegNo) override;
void emitDirectiveSetNoAt() override;
@@ -266,7 +185,6 @@ public:
void emitDirectiveSetMips64R5() override;
void emitDirectiveSetMips64R6() override;
void emitDirectiveSetDsp() override;
- void emitDirectiveSetDspr2() override;
void emitDirectiveSetNoDsp() override;
void emitDirectiveSetPop() override;
void emitDirectiveSetPush() override;
@@ -275,16 +193,8 @@ public:
// PIC support
void emitDirectiveCpLoad(unsigned RegNo) override;
-
- /// Emit a .cprestore directive. If the offset is out of range then it will
- /// be synthesized using the assembler temporary.
- ///
- /// GetATReg() is a callback that can be used to obtain the current assembler
- /// temporary and is only called when the assembler temporary is required. It
- /// must handle the case where no assembler temporary is available (typically
- /// by reporting an error).
- bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg,
- SMLoc IDLoc, const MCSubtargetInfo *STI) override;
+ void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts,
+ int Offset) override;
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg) override;
void emitDirectiveCpreturn(unsigned SaveLocation,
@@ -295,13 +205,6 @@ public:
void emitDirectiveModuleOddSPReg() override;
void emitDirectiveModuleSoftFloat() override;
void emitDirectiveModuleHardFloat() override;
- void emitDirectiveModuleMT() override;
- void emitDirectiveModuleCRC() override;
- void emitDirectiveModuleNoCRC() override;
- void emitDirectiveModuleVirt() override;
- void emitDirectiveModuleNoVirt() override;
- void emitDirectiveModuleGINV() override;
- void emitDirectiveModuleNoGINV() override;
void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value) override;
void emitDirectiveSetOddSPReg() override;
void emitDirectiveSetNoOddSPReg() override;
@@ -318,15 +221,12 @@ public:
MCELFStreamer &getStreamer();
MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
- void setPic(bool Value) override { Pic = Value; }
-
void emitLabel(MCSymbol *Symbol) override;
void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
void finish() override;
void emitDirectiveSetMicroMips() override;
void emitDirectiveSetNoMicroMips() override;
- void setUsesMicroMips() override;
void emitDirectiveSetMips16() override;
void emitDirectiveSetNoReorder() override;
@@ -346,8 +246,8 @@ public:
// PIC support
void emitDirectiveCpLoad(unsigned RegNo) override;
- bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg,
- SMLoc IDLoc, const MCSubtargetInfo *STI) override;
+ void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts,
+ int Offset) override;
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg) override;
void emitDirectiveCpreturn(unsigned SaveLocation,